@lenne.tech/ng-base 18.1.3 → 22.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +55 -0
- package/LICENSE +2 -2
- package/README.md +237 -44
- package/fesm2022/lenne.tech-ng-base-ai.mjs +767 -0
- package/fesm2022/lenne.tech-ng-base-ai.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-auth-provide.mjs +939 -0
- package/fesm2022/lenne.tech-ng-base-auth-provide.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-auth.mjs +454 -0
- package/fesm2022/lenne.tech-ng-base-auth.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-bug-bug-report-dialog-BRzVmKJr.mjs +825 -0
- package/fesm2022/lenne.tech-ng-base-bug-bug-report-dialog-BRzVmKJr.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-bug-bug-report-service-DWoTb_iw.mjs +351 -0
- package/fesm2022/lenne.tech-ng-base-bug-bug-report-service-DWoTb_iw.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-bug-capture-engine-TkjMDdqj.mjs +1046 -0
- package/fesm2022/lenne.tech-ng-base-bug-capture-engine-TkjMDdqj.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-bug-constants-Brm2KGHi.mjs +4 -0
- package/fesm2022/lenne.tech-ng-base-bug-constants-Brm2KGHi.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-bug-messages-BsP4fRQU.mjs +179 -0
- package/fesm2022/lenne.tech-ng-base-bug-messages-BsP4fRQU.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-bug-provide.mjs +26 -0
- package/fesm2022/lenne.tech-ng-base-bug-provide.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-bug-report-Tzlhe1Cm.mjs +62 -0
- package/fesm2022/lenne.tech-ng-base-bug-report-Tzlhe1Cm.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-bug-server.mjs +818 -0
- package/fesm2022/lenne.tech-ng-base-bug-server.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-bug.mjs +196 -0
- package/fesm2022/lenne.tech-ng-base-bug.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-files-ui.mjs +445 -0
- package/fesm2022/lenne.tech-ng-base-files-ui.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-files.mjs +474 -0
- package/fesm2022/lenne.tech-ng-base-files.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-server.mjs +408 -0
- package/fesm2022/lenne.tech-ng-base-server.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-share.mjs +76 -0
- package/fesm2022/lenne.tech-ng-base-share.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-sync.mjs +1096 -0
- package/fesm2022/lenne.tech-ng-base-sync.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-testing.mjs +171 -0
- package/fesm2022/lenne.tech-ng-base-testing.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-ui-provide.mjs +124 -0
- package/fesm2022/lenne.tech-ng-base-ui-provide.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-ui.mjs +34611 -0
- package/fesm2022/lenne.tech-ng-base-ui.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base-utils.mjs +287 -0
- package/fesm2022/lenne.tech-ng-base-utils.mjs.map +1 -0
- package/fesm2022/lenne.tech-ng-base.mjs +615 -910
- package/fesm2022/lenne.tech-ng-base.mjs.map +1 -1
- package/i18n/auth/de.json +17 -0
- package/i18n/auth/en.json +17 -0
- package/i18n/bug/de.json +85 -0
- package/i18n/bug/en.json +85 -0
- package/i18n/de.json +8 -0
- package/i18n/en.json +8 -0
- package/i18n/files/de.json +27 -0
- package/i18n/files/en.json +27 -0
- package/i18n/share/de.json +8 -0
- package/i18n/share/en.json +8 -0
- package/i18n/ui/de.json +38 -0
- package/i18n/ui/en.json +38 -0
- package/package.json +127 -58
- package/types/lenne.tech-ng-base-ai.d.ts +830 -0
- package/types/lenne.tech-ng-base-auth-provide.d.ts +603 -0
- package/types/lenne.tech-ng-base-auth.d.ts +320 -0
- package/types/lenne.tech-ng-base-bug-provide.d.ts +272 -0
- package/types/lenne.tech-ng-base-bug-rolldown-runtime-C25Le4-w.d.ts +1 -0
- package/types/lenne.tech-ng-base-bug-server.d.ts +316 -0
- package/types/lenne.tech-ng-base-bug.d.ts +202 -0
- package/types/lenne.tech-ng-base-files-ui.d.ts +116 -0
- package/types/lenne.tech-ng-base-files.d.ts +288 -0
- package/types/lenne.tech-ng-base-server.d.ts +262 -0
- package/types/lenne.tech-ng-base-share.d.ts +21 -0
- package/types/lenne.tech-ng-base-sync.d.ts +380 -0
- package/types/lenne.tech-ng-base-testing.d.ts +327 -0
- package/types/lenne.tech-ng-base-ui-provide.d.ts +65 -0
- package/types/lenne.tech-ng-base-ui.d.ts +7732 -0
- package/types/lenne.tech-ng-base-utils.d.ts +150 -0
- package/types/lenne.tech-ng-base.d.ts +503 -0
- package/ui/styles/components/accordion.css +3 -0
- package/ui/styles/components/alert-dialog.css +4 -0
- package/ui/styles/components/alert.css +3 -0
- package/ui/styles/components/aspect-ratio.css +3 -0
- package/ui/styles/components/attachment.css +4 -0
- package/ui/styles/components/autocomplete.css +4 -0
- package/ui/styles/components/avatar.css +3 -0
- package/ui/styles/components/badge.css +3 -0
- package/ui/styles/components/breadcrumb.css +3 -0
- package/ui/styles/components/bubble.css +3 -0
- package/ui/styles/components/button-group.css +3 -0
- package/ui/styles/components/button.css +3 -0
- package/ui/styles/components/calendar.css +5 -0
- package/ui/styles/components/card.css +3 -0
- package/ui/styles/components/checkbox.css +3 -0
- package/ui/styles/components/code-block.css +4 -0
- package/ui/styles/components/collapsible.css +3 -0
- package/ui/styles/components/combobox.css +5 -0
- package/ui/styles/components/command.css +5 -0
- package/ui/styles/components/context-menu.css +3 -0
- package/ui/styles/components/date-picker.css +7 -0
- package/ui/styles/components/dialog.css +4 -0
- package/ui/styles/components/drawer.css +3 -0
- package/ui/styles/components/dropdown-menu.css +3 -0
- package/ui/styles/components/empty.css +3 -0
- package/ui/styles/components/field.css +5 -0
- package/ui/styles/components/hover-card.css +3 -0
- package/ui/styles/components/index.css +91 -0
- package/ui/styles/components/input-group.css +6 -0
- package/ui/styles/components/input-otp.css +3 -0
- package/ui/styles/components/input.css +3 -0
- package/ui/styles/components/item.css +4 -0
- package/ui/styles/components/kbd.css +3 -0
- package/ui/styles/components/label.css +3 -0
- package/ui/styles/components/lt-breadcrumb.css +3 -0
- package/ui/styles/components/lt-bug-attachments.css +5 -0
- package/ui/styles/components/lt-bug-journey-timeline.css +5 -0
- package/ui/styles/components/lt-bug-report-dialog.css +15 -0
- package/ui/styles/components/lt-bug-report.css +4 -0
- package/ui/styles/components/lt-color-mode-button.css +3 -0
- package/ui/styles/components/lt-confirm-dialog.css +4 -0
- package/ui/styles/components/lt-data-view.css +5 -0
- package/ui/styles/components/lt-date-picker.css +3 -0
- package/ui/styles/components/lt-date-time-picker.css +5 -0
- package/ui/styles/components/lt-enter-action.css +2 -0
- package/ui/styles/components/lt-footer.css +3 -0
- package/ui/styles/components/lt-form-field.css +4 -0
- package/ui/styles/components/lt-header.css +5 -0
- package/ui/styles/components/lt-imports.css +21 -0
- package/ui/styles/components/lt-navigation-menu.css +3 -0
- package/ui/styles/components/lt-notice.css +3 -0
- package/ui/styles/components/lt-overlay-defaults.css +3 -0
- package/ui/styles/components/lt-page-card.css +3 -0
- package/ui/styles/components/lt-page-title.css +2 -0
- package/ui/styles/components/lt-password-input.css +4 -0
- package/ui/styles/components/lt-readonly-field.css +2 -0
- package/ui/styles/components/lt-select.css +4 -0
- package/ui/styles/components/lt-text-field.css +5 -0
- package/ui/styles/components/lt-toolbar-item.css +2 -0
- package/ui/styles/components/lt-toolbar.css +3 -0
- package/ui/styles/components/lt-tus-upload-component.css +5 -0
- package/ui/styles/components/marker.css +3 -0
- package/ui/styles/components/menubar.css +3 -0
- package/ui/styles/components/message-scroller.css +4 -0
- package/ui/styles/components/message.css +3 -0
- package/ui/styles/components/native-select.css +3 -0
- package/ui/styles/components/navigation-menu.css +3 -0
- package/ui/styles/components/pagination.css +4 -0
- package/ui/styles/components/popover.css +3 -0
- package/ui/styles/components/progress.css +3 -0
- package/ui/styles/components/questionnaire.css +4 -0
- package/ui/styles/components/radio-group.css +3 -0
- package/ui/styles/components/resizable.css +3 -0
- package/ui/styles/components/select.css +3 -0
- package/ui/styles/components/separator.css +3 -0
- package/ui/styles/components/sheet.css +4 -0
- package/ui/styles/components/sidebar.css +9 -0
- package/ui/styles/components/skeleton.css +3 -0
- package/ui/styles/components/slider.css +3 -0
- package/ui/styles/components/sonner.css +4 -0
- package/ui/styles/components/spinner.css +3 -0
- package/ui/styles/components/switch.css +3 -0
- package/ui/styles/components/table.css +3 -0
- package/ui/styles/components/tabs.css +4 -0
- package/ui/styles/components/textarea.css +3 -0
- package/ui/styles/components/toggle-group.css +4 -0
- package/ui/styles/components/toggle.css +3 -0
- package/ui/styles/components/tooltip.css +3 -0
- package/ui/styles/components/trace.css +3 -0
- package/ui/styles/components/typography.css +3 -0
- package/ui/styles/components/utils.css +2 -0
- package/ui/styles/core.css +137 -0
- package/ui/styles/palette.css +94 -0
- package/ui/styles/theme.css +14 -0
- package/ui/styles/transitions.css +131 -0
- package/base-cms/index.d.ts +0 -5
- package/base-cms/interfaces/base-cms-module-config.interface.d.ts +0 -16
- package/base-cms/pages/base-cms/base-cms.component.d.ts +0 -92
- package/base-cms/public-api.d.ts +0 -5
- package/base-components/components/breadcrumb/breadcrumb.component.d.ts +0 -10
- package/base-components/components/change-password/change-password.component.d.ts +0 -24
- package/base-components/components/checkbox/checkbox.component.d.ts +0 -12
- package/base-components/components/delete-account/delete-account.component.d.ts +0 -15
- package/base-components/components/fab-button/fab-button.component.d.ts +0 -16
- package/base-components/components/input/input.component.d.ts +0 -27
- package/base-components/components/loading-bar/loading-bar.component.d.ts +0 -17
- package/base-components/components/model-form/model-form-base.component.d.ts +0 -64
- package/base-components/components/model-form/model-form.component.d.ts +0 -139
- package/base-components/components/model-form-sub/model-form-sub.component.d.ts +0 -56
- package/base-components/components/model-table/model-table.component.d.ts +0 -115
- package/base-components/components/refence-input/refence-input.component.d.ts +0 -84
- package/base-components/components/select/select.component.d.ts +0 -25
- package/base-components/components/skeleton-loader/skeleton-loader.component.d.ts +0 -10
- package/base-components/components/tags/tags.component.d.ts +0 -60
- package/base-components/components/textarea/textarea.component.d.ts +0 -21
- package/base-components/components/toast/toast.component.d.ts +0 -19
- package/base-components/components/upload-image/upload-image.component.d.ts +0 -111
- package/base-components/directives/back-button.directive.d.ts +0 -9
- package/base-components/directives/context-menu.directive.d.ts +0 -22
- package/base-components/directives/sort.directive.d.ts +0 -15
- package/base-components/directives/stop-propagation.directive.d.ts +0 -10
- package/base-components/index.d.ts +0 -5
- package/base-components/pipes/ellipses.pipe.d.ts +0 -10
- package/base-components/public-api.d.ts +0 -26
- package/base-prototype/index.d.ts +0 -5
- package/base-prototype/pages/email-verification/email-verification.component.d.ts +0 -18
- package/base-prototype/pages/forgot-password/forgot-password.component.d.ts +0 -26
- package/base-prototype/pages/login/login.component.d.ts +0 -33
- package/base-prototype/pages/profile/profile.component.d.ts +0 -24
- package/base-prototype/pages/register/register.component.d.ts +0 -31
- package/base-prototype/pages/set-password/set-password.component.d.ts +0 -29
- package/base-prototype/public-api.d.ts +0 -9
- package/esm2022/base-cms/interfaces/base-cms-module-config.interface.mjs +0 -3
- package/esm2022/base-cms/lenne.tech-ng-base-base-cms.mjs +0 -5
- package/esm2022/base-cms/pages/base-cms/base-cms.component.mjs +0 -238
- package/esm2022/base-cms/public-api.mjs +0 -8
- package/esm2022/base-components/components/breadcrumb/breadcrumb.component.mjs +0 -23
- package/esm2022/base-components/components/change-password/change-password.component.mjs +0 -97
- package/esm2022/base-components/components/checkbox/checkbox.component.mjs +0 -38
- package/esm2022/base-components/components/delete-account/delete-account.component.mjs +0 -59
- package/esm2022/base-components/components/fab-button/fab-button.component.mjs +0 -24
- package/esm2022/base-components/components/input/input.component.mjs +0 -75
- package/esm2022/base-components/components/loading-bar/loading-bar.component.mjs +0 -37
- package/esm2022/base-components/components/model-form/model-form-base.component.mjs +0 -145
- package/esm2022/base-components/components/model-form/model-form.component.mjs +0 -591
- package/esm2022/base-components/components/model-form-sub/model-form-sub.component.mjs +0 -117
- package/esm2022/base-components/components/model-table/model-table.component.mjs +0 -478
- package/esm2022/base-components/components/refence-input/refence-input.component.mjs +0 -278
- package/esm2022/base-components/components/select/select.component.mjs +0 -62
- package/esm2022/base-components/components/skeleton-loader/skeleton-loader.component.mjs +0 -33
- package/esm2022/base-components/components/tags/tags.component.mjs +0 -227
- package/esm2022/base-components/components/textarea/textarea.component.mjs +0 -79
- package/esm2022/base-components/components/toast/toast.component.mjs +0 -69
- package/esm2022/base-components/components/upload-image/upload-image.component.mjs +0 -346
- package/esm2022/base-components/directives/back-button.directive.mjs +0 -25
- package/esm2022/base-components/directives/context-menu.directive.mjs +0 -112
- package/esm2022/base-components/directives/sort.directive.mjs +0 -61
- package/esm2022/base-components/directives/stop-propagation.directive.mjs +0 -24
- package/esm2022/base-components/lenne.tech-ng-base-base-components.mjs +0 -5
- package/esm2022/base-components/pipes/ellipses.pipe.mjs +0 -23
- package/esm2022/base-components/public-api.mjs +0 -30
- package/esm2022/base-prototype/lenne.tech-ng-base-base-prototype.mjs +0 -5
- package/esm2022/base-prototype/pages/email-verification/email-verification.component.mjs +0 -60
- package/esm2022/base-prototype/pages/forgot-password/forgot-password.component.mjs +0 -78
- package/esm2022/base-prototype/pages/login/login.component.mjs +0 -114
- package/esm2022/base-prototype/pages/profile/profile.component.mjs +0 -87
- package/esm2022/base-prototype/pages/register/register.component.mjs +0 -100
- package/esm2022/base-prototype/pages/set-password/set-password.component.mjs +0 -91
- package/esm2022/base-prototype/public-api.mjs +0 -11
- package/esm2022/lenne.tech-ng-base.mjs +0 -5
- package/esm2022/public-api.mjs +0 -25
- package/esm2022/shared/classes/auth.class.mjs +0 -14
- package/esm2022/shared/classes/basic-user.class.mjs +0 -49
- package/esm2022/shared/classes/graphql-enum.class.mjs +0 -10
- package/esm2022/shared/classes/graphql-meta.class.mjs +0 -345
- package/esm2022/shared/classes/graphql-type.class.mjs +0 -14
- package/esm2022/shared/classes/helper.class.mjs +0 -307
- package/esm2022/shared/classes/sort.class.mjs +0 -38
- package/esm2022/shared/classes/standard.class.mjs +0 -40
- package/esm2022/shared/decorators/debounce.decorator.mjs +0 -12
- package/esm2022/shared/enums/comparison-operator.enum.mjs +0 -16
- package/esm2022/shared/enums/graphql-request-type.enum.mjs +0 -10
- package/esm2022/shared/enums/logical-operator.enum.mjs +0 -10
- package/esm2022/shared/enums/skeleton-type.enum.mjs +0 -7
- package/esm2022/shared/enums/sort-order.enum.mjs +0 -6
- package/esm2022/shared/enums/toast-type.enum.mjs +0 -8
- package/esm2022/shared/functions/ws-client.function.mjs +0 -39
- package/esm2022/shared/interfaces/base-module-config.interface.mjs +0 -3
- package/esm2022/shared/interfaces/breadcrumb.interface.mjs +0 -2
- package/esm2022/shared/interfaces/can-component-deactivate.interface.mjs +0 -2
- package/esm2022/shared/interfaces/cms-enum-values.interface.mjs +0 -2
- package/esm2022/shared/interfaces/cms-field-config.interface.mjs +0 -2
- package/esm2022/shared/interfaces/cms-model-config.interface.mjs +0 -2
- package/esm2022/shared/interfaces/cms-table-field.interface.mjs +0 -2
- package/esm2022/shared/interfaces/combined-filter-input.interface.mjs +0 -2
- package/esm2022/shared/interfaces/compress-options.interface.mjs +0 -2
- package/esm2022/shared/interfaces/cropping-options.interface.mjs +0 -2
- package/esm2022/shared/interfaces/field-object.interface.mjs +0 -2
- package/esm2022/shared/interfaces/field.interface.mjs +0 -2
- package/esm2022/shared/interfaces/filter-input.interface.mjs +0 -2
- package/esm2022/shared/interfaces/find-args.interface.mjs +0 -2
- package/esm2022/shared/interfaces/graphql-crud-type.interface.mjs +0 -2
- package/esm2022/shared/interfaces/graphql-fields-object.interface.mjs +0 -2
- package/esm2022/shared/interfaces/graphql-options.interface.mjs +0 -2
- package/esm2022/shared/interfaces/graphql-plus-options.interfacen.mjs +0 -2
- package/esm2022/shared/interfaces/graphql-type-collection.interface.mjs +0 -2
- package/esm2022/shared/interfaces/login-config.interface.mjs +0 -2
- package/esm2022/shared/interfaces/register-config.interface.mjs +0 -2
- package/esm2022/shared/interfaces/single-filter-input.interface.mjs +0 -2
- package/esm2022/shared/interfaces/sort-input.interface.mjs +0 -2
- package/esm2022/shared/interfaces/time-components.interface.mjs +0 -2
- package/esm2022/shared/interfaces/toast.interface.mjs +0 -2
- package/esm2022/shared/lenne.tech-ng-base-shared.mjs +0 -5
- package/esm2022/shared/public-api.mjs +0 -74
- package/esm2022/shared/services/auth.service.mjs +0 -152
- package/esm2022/shared/services/breadcrumb.service.mjs +0 -69
- package/esm2022/shared/services/cms.service.mjs +0 -82
- package/esm2022/shared/services/file.service.mjs +0 -86
- package/esm2022/shared/services/forms.service.mjs +0 -61
- package/esm2022/shared/services/graphql-meta.service.mjs +0 -132
- package/esm2022/shared/services/graphql-plus.service.mjs +0 -93
- package/esm2022/shared/services/graphql.service.mjs +0 -510
- package/esm2022/shared/services/image.service.mjs +0 -102
- package/esm2022/shared/services/loader.service.mjs +0 -78
- package/esm2022/shared/services/navigation.service.mjs +0 -38
- package/esm2022/shared/services/scroll.service.mjs +0 -207
- package/esm2022/shared/services/storage.service.mjs +0 -149
- package/esm2022/shared/services/toast.service.mjs +0 -39
- package/esm2022/shared/services/user.service.mjs +0 -160
- package/esm2022/shared/services/ws.service.mjs +0 -17
- package/esm2022/shared/types/graphql-fields.type.mjs +0 -2
- package/esm2022/shared/types/storage.type.mjs +0 -2
- package/esm2022/shared/validators/email.validator.mjs +0 -7
- package/esm2022/shared/validators/match.validator.mjs +0 -22
- package/esm2022/shared/validators/secure-password.validator.mjs +0 -7
- package/esm2022/src/base.module.mjs +0 -64
- package/esm2022/src/decorators/auto-unsubscribe.decorator.mjs +0 -23
- package/esm2022/src/directives/lazy-load.directive.mjs +0 -48
- package/esm2022/src/directives/match-height.directive.mjs +0 -92
- package/esm2022/src/directives/resizable.directive.mjs +0 -92
- package/esm2022/src/factories/apollo-options.factory.mjs +0 -108
- package/esm2022/src/functions/extract-files.function.mjs +0 -87
- package/esm2022/src/guards/auth.guard.mjs +0 -91
- package/esm2022/src/guards/can-deactivate.guard.mjs +0 -16
- package/esm2022/src/guards/logout.guard.mjs +0 -34
- package/esm2022/src/pipes/date-ago.pipe.mjs +0 -64
- package/esm2022/src/pipes/safe-html.pipe.mjs +0 -22
- package/esm2022/src/services/fullscreen.service.mjs +0 -51
- package/esm2022/src/services/seo.service.mjs +0 -117
- package/esm2022/src/services/theme.service.mjs +0 -44
- package/fesm2022/lenne.tech-ng-base-base-cms.mjs +0 -251
- package/fesm2022/lenne.tech-ng-base-base-cms.mjs.map +0 -1
- package/fesm2022/lenne.tech-ng-base-base-components.mjs +0 -2917
- package/fesm2022/lenne.tech-ng-base-base-components.mjs.map +0 -1
- package/fesm2022/lenne.tech-ng-base-base-prototype.mjs +0 -505
- package/fesm2022/lenne.tech-ng-base-base-prototype.mjs.map +0 -1
- package/fesm2022/lenne.tech-ng-base-shared.mjs +0 -2863
- package/fesm2022/lenne.tech-ng-base-shared.mjs.map +0 -1
- package/index.d.ts +0 -5
- package/public-api.d.ts +0 -17
- package/shared/classes/auth.class.d.ts +0 -10
- package/shared/classes/basic-user.class.d.ts +0 -27
- package/shared/classes/graphql-enum.class.d.ts +0 -7
- package/shared/classes/graphql-meta.class.d.ts +0 -66
- package/shared/classes/graphql-type.class.d.ts +0 -13
- package/shared/classes/helper.class.d.ts +0 -99
- package/shared/classes/sort.class.d.ts +0 -12
- package/shared/classes/standard.class.d.ts +0 -32
- package/shared/decorators/debounce.decorator.d.ts +0 -1
- package/shared/enums/comparison-operator.enum.d.ts +0 -14
- package/shared/enums/graphql-request-type.enum.d.ts +0 -8
- package/shared/enums/logical-operator.enum.d.ts +0 -8
- package/shared/enums/skeleton-type.enum.d.ts +0 -5
- package/shared/enums/sort-order.enum.d.ts +0 -4
- package/shared/enums/toast-type.enum.d.ts +0 -6
- package/shared/functions/ws-client.function.d.ts +0 -5
- package/shared/index.d.ts +0 -5
- package/shared/interfaces/base-module-config.interface.d.ts +0 -61
- package/shared/interfaces/breadcrumb.interface.d.ts +0 -4
- package/shared/interfaces/can-component-deactivate.interface.d.ts +0 -7
- package/shared/interfaces/cms-enum-values.interface.d.ts +0 -4
- package/shared/interfaces/cms-field-config.interface.d.ts +0 -45
- package/shared/interfaces/cms-model-config.interface.d.ts +0 -14
- package/shared/interfaces/cms-table-field.interface.d.ts +0 -10
- package/shared/interfaces/combined-filter-input.interface.d.ts +0 -9
- package/shared/interfaces/compress-options.interface.d.ts +0 -15
- package/shared/interfaces/cropping-options.interface.d.ts +0 -12
- package/shared/interfaces/field-object.interface.d.ts +0 -6
- package/shared/interfaces/field.interface.d.ts +0 -5
- package/shared/interfaces/filter-input.interface.d.ts +0 -9
- package/shared/interfaces/find-args.interface.d.ts +0 -11
- package/shared/interfaces/graphql-crud-type.interface.d.ts +0 -7
- package/shared/interfaces/graphql-fields-object.interface.d.ts +0 -6
- package/shared/interfaces/graphql-options.interface.d.ts +0 -11
- package/shared/interfaces/graphql-plus-options.interfacen.d.ts +0 -9
- package/shared/interfaces/graphql-type-collection.interface.d.ts +0 -7
- package/shared/interfaces/login-config.interface.d.ts +0 -6
- package/shared/interfaces/register-config.interface.d.ts +0 -4
- package/shared/interfaces/single-filter-input.interface.d.ts +0 -11
- package/shared/interfaces/sort-input.interface.d.ts +0 -5
- package/shared/interfaces/time-components.interface.d.ts +0 -6
- package/shared/interfaces/toast.interface.d.ts +0 -8
- package/shared/public-api.d.ts +0 -65
- package/shared/services/auth.service.d.ts +0 -44
- package/shared/services/breadcrumb.service.d.ts +0 -32
- package/shared/services/cms.service.d.ts +0 -27
- package/shared/services/file.service.d.ts +0 -22
- package/shared/services/forms.service.d.ts +0 -14
- package/shared/services/graphql-meta.service.d.ts +0 -45
- package/shared/services/graphql-plus.service.d.ts +0 -27
- package/shared/services/graphql.service.d.ts +0 -71
- package/shared/services/image.service.d.ts +0 -27
- package/shared/services/loader.service.d.ts +0 -32
- package/shared/services/navigation.service.d.ts +0 -15
- package/shared/services/scroll.service.d.ts +0 -85
- package/shared/services/storage.service.d.ts +0 -49
- package/shared/services/toast.service.d.ts +0 -15
- package/shared/services/user.service.d.ts +0 -77
- package/shared/services/ws.service.d.ts +0 -8
- package/shared/types/graphql-fields.type.d.ts +0 -5
- package/shared/types/storage.type.d.ts +0 -4
- package/shared/validators/email.validator.d.ts +0 -1
- package/shared/validators/match.validator.d.ts +0 -4
- package/shared/validators/secure-password.validator.d.ts +0 -1
- package/src/base.module.d.ts +0 -16
- package/src/decorators/auto-unsubscribe.decorator.d.ts +0 -5
- package/src/directives/lazy-load.directive.d.ts +0 -17
- package/src/directives/match-height.directive.d.ts +0 -20
- package/src/directives/resizable.directive.d.ts +0 -26
- package/src/factories/apollo-options.factory.d.ts +0 -16
- package/src/functions/extract-files.function.d.ts +0 -15
- package/src/guards/auth.guard.d.ts +0 -27
- package/src/guards/can-deactivate.guard.d.ts +0 -10
- package/src/guards/logout.guard.d.ts +0 -16
- package/src/pipes/date-ago.pipe.d.ts +0 -34
- package/src/pipes/safe-html.pipe.d.ts +0 -13
- package/src/services/fullscreen.service.d.ts +0 -18
- package/src/services/seo.service.d.ts +0 -61
- package/src/services/theme.service.d.ts +0 -17
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lenne.tech-ng-base-bug-capture-engine-TkjMDdqj.mjs","names":[],"sources":["../../../projects/ng-base/bug/src/lib/redact.ts","../../../projects/ng-base/bug/src/lib/browser-info.ts","../../../projects/ng-base/bug/src/lib/ring-buffer.ts","../../../projects/ng-base/bug/src/lib/console-capture.ts","../../../projects/ng-base/bug/src/lib/error-capture.ts","../../../projects/ng-base/bug/src/lib/journey-capture.ts","../../../projects/ng-base/bug/src/lib/network-capture.ts","../../../projects/ng-base/bug/src/lib/capture-engine.ts"],"sourcesContent":["/*\n * Redaction of secrets in captured data (headers, URLs, bodies, console text).\n *\n * Pure TypeScript without DOM or Angular. `@lenne.tech/ng-base/bug/server` carries an identical copy\n * (`bug/server/src/lib/redact.ts`), so the server applies the same patterns once more before it writes to Linear;\n * `redact-parity.spec.ts` keeps both copies in sync.\n */\n\n/** Replacement of every redacted value. */\nexport const LT_BUG_REDACTED = '[redacted]';\n\n/** Headers whose values are never recorded (compared case-insensitively). */\nexport const LT_BUG_SENSITIVE_HEADERS: readonly string[] = Object.freeze([\n 'api-key',\n 'authorization',\n 'cookie',\n 'proxy-authorization',\n 'set-cookie',\n 'x-access-token',\n 'x-api-key',\n 'x-auth-token',\n 'x-csrf-token',\n 'x-system-setup-token',\n 'x-xsrf-token',\n]);\n\n/**\n * Path segments whose request and response bodies are never recorded: nest-server IAM (`/iam/…`: passwords, tokens,\n * 2FA codes, reset and verify tokens), the first-admin setup (`/system-setup/…`) and other auth-like endpoints.\n */\nexport const LT_BUG_BODY_EXCLUDED_SEGMENTS: readonly string[] = Object.freeze([\n 'auth',\n 'iam',\n 'login',\n 'logout',\n 'oauth',\n 'oauth2',\n 'passkey',\n 'reset-password',\n 'sign-in',\n 'sign-up',\n 'signin',\n 'signup',\n 'system-setup',\n 'token',\n 'two-factor',\n 'verify-email',\n]);\n\n/** Key fragments that mark a value as secret (key lower-cased, `-`/`_` removed). */\nconst SENSITIVE_KEY_PARTS = [\n 'apikey',\n 'authorization',\n 'backupcode',\n 'cardnumber',\n 'cookie',\n 'credential',\n 'creditcard',\n 'passwd',\n 'password',\n 'privatekey',\n 'recoverycode',\n 'secret',\n 'signature',\n 'token',\n 'totp',\n 'twofactor',\n 'verificationcode',\n];\n\n/** Keys that are secret as a whole (`code` from OAuth / email links, `otp`, `pin` …). */\nconst SENSITIVE_KEYS = new Set(['auth', 'code', 'csc', 'cvc', 'cvv', 'iban', 'jwt', 'otp', 'pin', 'pwd', 'sessionid', 'sid', 'ssn']);\n\nconst SENSITIVE_HEADER_SET = new Set(LT_BUG_SENSITIVE_HEADERS);\nconst BODY_EXCLUDED = new RegExp(`/(?:${LT_BUG_BODY_EXCLUDED_SEGMENTS.map((segment) => segment.replace(/[-/]/g, '\\\\$&')).join('|')})(?:[/?#;]|$)`, 'i');\n\nconst USERINFO = /\\b([a-z][a-z\\d+.-]*:\\/\\/)[^\\s/?#@:]+:[^\\s/?#@]+@/gi;\nconst JWT = /\\beyJ[\\w-]{5,}\\.[\\w-]{5,}\\.[\\w-]*/g;\nconst BEARER = /\\b(Bearer)\\s+(?=[\\w\\-.~+/]*[\\d.\\-_~+/])[\\w\\-.~+/]{8,}=*/g;\nconst PATH_TOKEN = /(\\/(?:activate|confirm-email|email-verification|invitation|invite|magic-link|reset-password|verify-email)\\/)[^/?#\\s\"'<>]+/gi;\nconst PARAM = /(^|[?&#;\\s\"'(,{]|%3[fF]|%26|%23)((?:[\\w.\\-~[\\]]|%5[bBdD])+)(=|%3[dD])([^&#;\\s\"'<>)}]*?)(?=$|[&#;\\s\"'<>)}]|%26|%23)/g;\nconst JSON_PAIR = /(\"((?:[^\"\\\\]|\\\\.)*)\"\\s*:\\s*)(\"(?:[^\"\\\\]|\\\\.)*\"|-?\\d[\\d.eE+-]*|true|false|null)/g;\nconst JSON_PAIR_OPEN = /(\"((?:[^\"\\\\]|\\\\.)*)\"\\s*:\\s*)\"(?:[^\"\\\\]|\\\\.)*$/;\nconst LABELLED = /\\b(api[-_]?key|otp|passwd|password|secret|token)(\\s*:\\s*)(\"[^\"]*\"|'[^']*'|[^\\s,;]+)/gi;\n\n/** Whether a header carries credentials (`Authorization`, `Cookie`, `Set-Cookie`, `X-System-Setup-Token` …). */\nexport function isLtSensitiveHeader(name: string): boolean {\n return SENSITIVE_HEADER_SET.has(name.trim().toLowerCase());\n}\n\n/**\n * Whether an object key / form field name / query parameter holds a secret (`password`, `newPassword`, `token`,\n * `access_token`, `code`, `otp`, `user[password]` …).\n */\nexport function isLtSensitiveKey(key: string): boolean {\n const decoded = safeDecode(key);\n const last =\n decoded\n .split(/[[\\].]/)\n .filter(Boolean)\n .pop() ?? decoded;\n const normalized = last.toLowerCase().replace(/[-_\\s]/g, '');\n return SENSITIVE_KEYS.has(normalized) || SENSITIVE_KEY_PARTS.some((part) => normalized.includes(part));\n}\n\n/** Whether request and response bodies of `url` must not be recorded (see {@link LT_BUG_BODY_EXCLUDED_SEGMENTS}). */\nexport function isLtBodyExcludedUrl(url: string): boolean {\n const path = url.replace(/^[a-z][a-z\\d+.-]*:\\/\\/[^/?#]*/i, '').split(/[?#]/)[0] ?? '';\n return BODY_EXCLUDED.test(path);\n}\n\n/**\n * Redact secrets in free text and URLs: query/hash/form parameters (`token`, `code`, `password`, `secret`, `otp`, …,\n * also inside nested and percent-encoded `callbackURL` values), tokens in reset/verify paths, URL credentials,\n * `Bearer` tokens, JWTs, JSON pairs with secret keys and `password: …` labels.\n */\nexport function redactLtText(text: string): string {\n if (!text) {\n return text;\n }\n let result = text.replace(USERINFO, `$1${LT_BUG_REDACTED}@`).replace(JWT, LT_BUG_REDACTED).replace(BEARER, `$1 ${LT_BUG_REDACTED}`).replace(PATH_TOKEN, `$1${LT_BUG_REDACTED}`);\n result = redactParams(result, 0);\n result = result.replace(JSON_PAIR, (match, prefix: string, key: string) => (isLtSensitiveKey(key) ? `${prefix}\"${LT_BUG_REDACTED}\"` : match));\n result = result.replace(JSON_PAIR_OPEN, (match, prefix: string, key: string) => (isLtSensitiveKey(key) ? `${prefix}\"${LT_BUG_REDACTED}\"` : match));\n return result.replace(LABELLED, `$1$2${LT_BUG_REDACTED}`);\n}\n\n/** Redact a URL (alias of {@link redactLtText}, which handles URLs inside text as well). */\nexport function redactLtUrl(url: string): string {\n return redactLtText(url);\n}\n\n/** Deep copy of a parsed JSON value with secret keys replaced and every string redacted. */\nexport function redactLtValue(value: unknown, depth = 0): unknown {\n if (typeof value === 'string') {\n return redactLtText(value);\n }\n if (depth > 20 || value === null || typeof value !== 'object') {\n return depth > 20 ? LT_BUG_REDACTED : value;\n }\n if (Array.isArray(value)) {\n return value.map((item) => redactLtValue(item, depth + 1));\n }\n const result: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) {\n result[key] = isLtSensitiveKey(key) ? LT_BUG_REDACTED : redactLtValue(item, depth + 1);\n }\n return result;\n}\n\n/** Redact and truncate a request/response body: JSON deep, everything else (form data, text) as text. */\nexport function redactLtBody(body: string, maxLength = 1000): string {\n const input = body.length > 20_000 ? body.slice(0, 20_000) : body;\n const trimmed = input.trim();\n let redacted: string;\n if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n try {\n redacted = JSON.stringify(redactLtValue(JSON.parse(trimmed)));\n } catch {\n redacted = redactLtText(input);\n }\n } else {\n redacted = redactLtText(input);\n }\n return truncateLt(redacted, maxLength);\n}\n\n/** Copy of a header map with credential headers replaced by `[redacted]` and the other values redacted as text. */\nexport function redactLtHeaders(headers: Record<string, string>): Record<string, string> {\n const result: Record<string, string> = {};\n for (const [name, value] of Object.entries(headers)) {\n result[name] = isLtSensitiveHeader(name) ? LT_BUG_REDACTED : redactLtText(String(value));\n }\n return result;\n}\n\n/** Cut `text` to `maxLength` characters with a marker naming the dropped length. */\nexport function truncateLt(text: string, maxLength: number): string {\n return text.length <= maxLength ? text : `${text.slice(0, maxLength)}... [truncated ${text.length - maxLength} characters]`;\n}\n\nfunction redactParams(text: string, depth: number): string {\n return text.replace(PARAM, (match, separator: string, key: string, equals: string, value: string) => {\n if (isLtSensitiveKey(key)) {\n return `${separator}${key}${equals}${value ? LT_BUG_REDACTED : ''}`;\n }\n // Nested URLs (`callbackURL=https://app/verify?token=…`, also percent-encoded) carry their own parameters.\n if (depth < 3 && /=|%3[dD]/.test(value)) {\n return `${separator}${key}${equals}${redactParams(value, depth + 1)}`;\n }\n return match;\n });\n}\n\nfunction safeDecode(value: string): string {\n try {\n return decodeURIComponent(value);\n } catch {\n return value;\n }\n}\n","import type { LtBrowserInfo } from './bug-types';\nimport { redactLtUrl } from './redact';\n\nconst BROWSERS: readonly { name: string; regex: RegExp }[] = [\n { name: 'Edge', regex: /Edg(?:e|A|iOS)?\\/([\\d.]+)/ },\n { name: 'Opera', regex: /(?:OPR|Opera)\\/([\\d.]+)/ },\n { name: 'Firefox', regex: /(?:Firefox|FxiOS)\\/([\\d.]+)/ },\n { name: 'Chrome', regex: /(?:Chrome|CriOS)\\/([\\d.]+)/ },\n { name: 'Safari', regex: /Version\\/([\\d.]+).*Safari/ },\n];\n\nconst SYSTEMS: readonly { name: string; regex: RegExp }[] = [\n { name: 'Windows', regex: /Windows NT ([\\d.]+)/ },\n { name: 'Android', regex: /Android ([\\d.]+)/ },\n { name: 'iOS', regex: /(?:iPhone|iPad|iPod).*? OS ([\\d_]+)/ },\n { name: 'macOS', regex: /Mac OS X ([\\d_.]+)/ },\n { name: 'Linux', regex: /Linux/ },\n];\n\n/** Browser name and version from a user agent (Edge and Opera before Chrome, Safari by its `Version/`). */\nexport function detectLtBrowser(userAgent: string): { name: string; version: string } {\n for (const browser of BROWSERS) {\n const match = browser.regex.exec(userAgent);\n if (match) {\n return { name: browser.name, version: match[1] ?? 'Unknown' };\n }\n }\n return { name: 'Unknown', version: 'Unknown' };\n}\n\n/** Operating system from a user agent (iOS before macOS, Android before Linux). */\nexport function detectLtOs(userAgent: string): { name: string; version: string } {\n for (const system of SYSTEMS) {\n const match = system.regex.exec(userAgent);\n if (match) {\n return { name: system.name, version: match[1] ? match[1].replace(/_/g, '.') : 'Unknown' };\n }\n }\n return { name: 'Unknown', version: 'Unknown' };\n}\n\n/**\n * Browser, OS, viewport, screen, locale and navigation timing of the current page. Page URL and referrer are redacted.\n * Throws outside the browser.\n */\nexport function getLtBrowserInfo(view: (Window & typeof globalThis) | null | undefined = typeof window === 'undefined' ? undefined : window): LtBrowserInfo {\n if (!view?.navigator) {\n throw new TypeError('Browser info collection is only available in the browser');\n }\n const { document, location, navigator, screen } = view;\n let timezone = 'Unknown';\n try {\n timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || 'Unknown';\n } catch {\n // Keep 'Unknown'.\n }\n return {\n browser: detectLtBrowser(navigator.userAgent ?? ''),\n cookieEnabled: !!navigator.cookieEnabled,\n language: navigator.language,\n languages: navigator.languages?.length ? [...navigator.languages] : [navigator.language],\n onLine: !!navigator.onLine,\n os: detectLtOs(navigator.userAgent ?? ''),\n performance: performanceInfo(view),\n platform: navigator.platform ?? '',\n referrer: document?.referrer ? redactLtUrl(document.referrer) : '',\n screen: { colorDepth: screen?.colorDepth ?? 0, height: screen?.height ?? 0, pixelDepth: screen?.pixelDepth ?? 0, width: screen?.width ?? 0 },\n timestamp: new Date().toISOString(),\n timezone,\n title: document?.title ?? '',\n url: redactLtUrl(location?.href ?? ''),\n userAgent: navigator.userAgent ?? '',\n vendor: navigator.vendor ?? '',\n viewport: {\n height: view.innerHeight || document?.documentElement?.clientHeight || 0,\n width: view.innerWidth || document?.documentElement?.clientWidth || 0,\n },\n };\n}\n\nfunction performanceInfo(view: Window): LtBrowserInfo['performance'] {\n const performance = view.performance;\n if (!performance?.getEntriesByType) {\n return undefined;\n }\n const navigation = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming | undefined;\n if (!navigation) {\n return undefined;\n }\n const paint = (name: string) => performance.getEntriesByName?.(name)[0]?.startTime ?? null;\n return {\n domComplete: navigation.domComplete,\n domContentLoaded: navigation.domContentLoadedEventEnd - navigation.domContentLoadedEventStart,\n firstContentfulPaint: paint('first-contentful-paint'),\n firstPaint: paint('first-paint'),\n loadTime: navigation.loadEventEnd - navigation.loadEventStart,\n navigationStart: navigation.fetchStart,\n responseEnd: navigation.responseEnd,\n };\n}\n","/** Fixed-size buffer that keeps the newest entries (the oldest drops out when full). */\nexport class LtRingBuffer<T> {\n private items: T[] = [];\n\n constructor(private readonly capacity: number) {}\n\n /** Number of stored entries. */\n get size(): number {\n return this.items.length;\n }\n\n /** Append an entry; drops the oldest one when the buffer is full. */\n push(item: T): void {\n this.items.push(item);\n if (this.items.length > this.capacity) {\n this.items.splice(0, this.items.length - this.capacity);\n }\n }\n\n /** The newest `limit` entries (default all), oldest first, as shallow copies. */\n toArray(limit = this.capacity): T[] {\n return this.items.slice(-Math.max(0, limit)).map((item) => (item && typeof item === 'object' ? { ...item } : item));\n }\n\n /** The newest entry (live reference, for later enrichment), `undefined` when empty. */\n last(): T | undefined {\n return this.items[this.items.length - 1];\n }\n\n /** Remove every entry. */\n clear(): void {\n this.items = [];\n }\n}\n","import type { LtConsoleLogEntry } from './bug-types';\nimport { redactLtText, truncateLt } from './redact';\nimport { LtRingBuffer } from './ring-buffer';\n\nconst LEVELS = ['log', 'info', 'warn', 'error', 'debug'] as const;\nconst MAX_PART_LENGTH = 2000;\nconst MAX_STACK_LENGTH = 5000;\n\ntype ConsoleMethod = (...args: unknown[]) => void;\n\n/**\n * Wraps `console.log/info/warn/error/debug` and records every call in a ring buffer: `%c` placeholders and their CSS\n * arguments are dropped, objects\n * serialised, secrets redacted (see `redactLtText`). Uncaught errors and unhandled rejections are recorded as well,\n * unless another listener (Angular's global error listeners) already logged them through `console.error`.\n * The original methods keep running unchanged.\n */\nexport class LtConsoleCapture {\n private readonly buffer: LtRingBuffer<LtConsoleLogEntry>;\n private originals: Partial<Record<(typeof LEVELS)[number], ConsoleMethod>> | null = null;\n private wrappers: Partial<Record<(typeof LEVELS)[number], ConsoleMethod>> = {};\n private removeListeners: (() => void) | null = null;\n\n constructor(\n capacity: number,\n private readonly target: Pick<Console, (typeof LEVELS)[number]> = console,\n ) {\n this.buffer = new LtRingBuffer(capacity);\n }\n\n /** Whether the console is currently wrapped. */\n get installed(): boolean {\n return this.originals !== null;\n }\n\n /** Wrap the console (idempotent) and listen for uncaught errors on `view`. */\n install(view?: Pick<Window, 'addEventListener' | 'removeEventListener'> | null): void {\n if (this.originals) {\n return;\n }\n const target = this.target as unknown as Record<string, ConsoleMethod>;\n this.originals = {};\n for (const level of LEVELS) {\n const original = target[level];\n if (typeof original !== 'function') {\n continue;\n }\n this.originals[level] = original;\n const wrapper: ConsoleMethod = (...args: unknown[]) => {\n original.apply(this.target, args);\n try {\n this.record(level, args);\n } catch {\n // Capturing must never break logging.\n }\n };\n this.wrappers[level] = wrapper;\n target[level] = wrapper;\n }\n if (view) {\n const onError = (event: ErrorEvent) =>\n queueMicrotask(() => {\n if (!event.defaultPrevented) {\n this.push({ level: 'error', message: [redactLtText(truncateLt(event.message || 'Error', MAX_PART_LENGTH))], stack: stackOf(event.error), timestamp: now() });\n }\n });\n const onRejection = (event: PromiseRejectionEvent) =>\n queueMicrotask(() => {\n if (!event.defaultPrevented) {\n this.push({ level: 'error', message: [serialize(event.reason)], stack: stackOf(event.reason), timestamp: now() });\n }\n });\n view.addEventListener('error', onError as EventListener);\n view.addEventListener('unhandledrejection', onRejection as EventListener);\n this.removeListeners = () => {\n view.removeEventListener('error', onError as EventListener);\n view.removeEventListener('unhandledrejection', onRejection as EventListener);\n };\n }\n }\n\n /** Restore the original console methods (only those still wrapped by this instance) and remove the listeners. */\n uninstall(): void {\n if (!this.originals) {\n return;\n }\n const target = this.target as unknown as Record<string, ConsoleMethod>;\n for (const level of LEVELS) {\n const original = this.originals[level];\n if (original && target[level] === this.wrappers[level]) {\n target[level] = original;\n }\n }\n this.originals = null;\n this.wrappers = {};\n this.removeListeners?.();\n this.removeListeners = null;\n }\n\n /** The newest `limit` entries, oldest first. */\n entries(limit?: number): LtConsoleLogEntry[] {\n return this.buffer.toArray(limit);\n }\n\n /** Number of stored entries. */\n get size(): number {\n return this.buffer.size;\n }\n\n /** Remove every entry. */\n clear(): void {\n this.buffer.clear();\n }\n\n private record(level: LtConsoleLogEntry['level'], args: unknown[]): void {\n const message = withoutStyleArguments(args)\n .map((arg) => serialize(arg))\n .filter((part) => part.length > 0);\n const entry: LtConsoleLogEntry = { level, message, timestamp: now() };\n if (level === 'error') {\n const error = args.find((arg) => arg instanceof Error);\n if (error) {\n entry.stack = stackOf(error);\n }\n }\n this.push(entry);\n }\n\n private push(entry: LtConsoleLogEntry): void {\n this.buffer.push(entry);\n }\n}\n\n/** Serialise one console argument: strings without `%c` and collapsed whitespace, errors by message, objects as JSON. */\nfunction serialize(arg: unknown): string {\n let text: string;\n if (typeof arg === 'string') {\n text = arg.replace(/%c/g, '').replace(/\\s+/g, ' ').trim();\n } else if (arg instanceof Error) {\n text = arg.message;\n } else {\n try {\n text = JSON.stringify(arg, null, 2) ?? String(arg);\n } catch {\n text = String(arg);\n }\n }\n return truncateLt(redactLtText(text.length > 20_000 ? text.slice(0, 20_000) : text), MAX_PART_LENGTH);\n}\n\n/** Drop the CSS arguments that belong to `%c` placeholders of the first argument (`console.log('%cHi', 'color: red')`). */\nfunction withoutStyleArguments(args: unknown[]): unknown[] {\n const [first, ...rest] = args;\n if (typeof first !== 'string' || !first.includes('%c')) {\n return args;\n }\n const styles = first.match(/%c/g)?.length ?? 0;\n return [first, ...rest.filter((arg, index) => index >= styles || typeof arg !== 'string')];\n}\n\nfunction stackOf(error: unknown): string | undefined {\n const stack = (error as { stack?: unknown } | null | undefined)?.stack;\n return typeof stack === 'string' ? truncateLt(redactLtText(stack), MAX_STACK_LENGTH) : undefined;\n}\n\nfunction now(): string {\n return new Date().toISOString();\n}\n","import type { ErrorHandler } from '@angular/core';\n\nimport type { LtBugErrorInfo } from './bug-types';\nimport { redactLtText, redactLtUrl, truncateLt } from './redact';\n\nconst DEDUPE_MS = 1000;\n\n/** The window members the error capture listens on. */\nexport type LtErrorCaptureWindow = Pick<Window, 'addEventListener' | 'location' | 'navigator' | 'removeEventListener'>;\n\n/**\n * Wrap `handler.handleError` so `listener` sees every error first; the app's handler (Angular's default or its own)\n * keeps handling each error exactly as before. Returns a function that restores the original method.\n */\nexport function ltWrapErrorHandler(handler: ErrorHandler, listener: (error: unknown) => void): () => void {\n const hadOwn = Object.prototype.hasOwnProperty.call(handler, 'handleError');\n const original = handler.handleError;\n const wrapped = function (this: ErrorHandler, error: unknown): void {\n try {\n listener(error);\n } catch {\n // The reporter must never break error handling.\n }\n original.call(this, error);\n };\n handler.handleError = wrapped;\n return () => {\n if (handler.handleError !== wrapped) {\n return;\n }\n if (hadOwn) {\n handler.handleError = original;\n } else {\n delete (handler as Partial<ErrorHandler>).handleError;\n }\n };\n}\n\n/** Normalised, redacted error information. */\nexport function toLtBugErrorInfo(error: unknown, componentName: string | undefined, view?: Pick<Window, 'location' | 'navigator'> | null): LtBugErrorInfo {\n const candidate = error as { message?: unknown; stack?: unknown } | null | undefined;\n const message = typeof error === 'string' ? error : typeof candidate?.message === 'string' && candidate.message ? candidate.message : String(error ?? 'Unknown error');\n const stack = typeof candidate?.stack === 'string' ? candidate.stack : undefined;\n return {\n componentName,\n message: truncateLt(redactLtText(message), 1000),\n stack: stack ? truncateLt(redactLtText(stack), 5000) : undefined,\n timestamp: new Date().toISOString(),\n url: view?.location?.href ? redactLtUrl(view.location.href) : undefined,\n userAgent: view?.navigator?.userAgent,\n };\n}\n\n/**\n * Captures errors from the Angular `ErrorHandler` (wrapped, see {@link ltWrapErrorHandler}) and from uncaught errors\n * and unhandled rejections on the window, and hands each one once to `onError` (the same error object, or the same\n * message within a second, is reported once — Angular's global error listeners forward window errors to the handler\n * as well).\n */\nexport class LtErrorCapture {\n private readonly seen = new WeakSet<object>();\n private lastMessage: { at: number; message: string } | null = null;\n private cleanups: (() => void)[] = [];\n private view: LtErrorCaptureWindow | null = null;\n\n constructor(private readonly onError: (info: LtBugErrorInfo, error: unknown) => void) {}\n\n /** Whether the capture is installed. */\n get installed(): boolean {\n return this.cleanups.length > 0;\n }\n\n /** Wrap `handler` and listen on `view` (idempotent). */\n install(handler: ErrorHandler | null, view: LtErrorCaptureWindow | null): void {\n if (this.installed) {\n return;\n }\n this.view = view;\n if (handler) {\n this.cleanups.push(ltWrapErrorHandler(handler, (error) => this.report(error, 'ErrorHandler')));\n }\n if (view) {\n const onError = (event: ErrorEvent) => this.report(event.error ?? event.message, 'window');\n const onRejection = (event: PromiseRejectionEvent) => this.report(event.reason, 'unhandledrejection');\n view.addEventListener('error', onError as EventListener);\n view.addEventListener('unhandledrejection', onRejection as EventListener);\n this.cleanups.push(() => {\n view.removeEventListener('error', onError as EventListener);\n view.removeEventListener('unhandledrejection', onRejection as EventListener);\n });\n }\n if (!this.cleanups.length) {\n this.cleanups.push(() => undefined);\n }\n }\n\n /** Restore the handler and remove the listeners. */\n uninstall(): void {\n while (this.cleanups.length) {\n this.cleanups.pop()?.();\n }\n this.view = null;\n }\n\n /** Report an error (also used for `LtBugReportService.reportError()`); duplicates are dropped. */\n report(error: unknown, componentName?: string): void {\n if (error && typeof error === 'object') {\n if (this.seen.has(error)) {\n return;\n }\n this.seen.add(error);\n }\n const info = toLtBugErrorInfo(error, componentName, this.view);\n const at = Date.now();\n if (this.lastMessage && this.lastMessage.message === info.message && at - this.lastMessage.at < DEDUPE_MS) {\n return;\n }\n this.lastMessage = { at, message: info.message };\n this.onError(info, error);\n }\n}\n","import type { LtBugUserJourneyOptions, LtUserInteractionEvent, LtUserInteractionMetadata, LtUserInteractionType } from './bug-types';\nimport { LT_BUG_UI_ATTRIBUTE } from './constants';\nimport { isLtSensitiveKey, redactLtText, redactLtUrl, truncateLt } from './redact';\nimport { LtRingBuffer } from './ring-buffer';\n\nconst INTERACTIVE = 'a,button,input,label,select,summary,textarea,[role=\"button\"],[role=\"checkbox\"],[role=\"link\"],[role=\"menuitem\"],[role=\"option\"],[role=\"switch\"],[role=\"tab\"]';\nconst DIALOG = '[role=\"dialog\"],[role=\"alertdialog\"],dialog[open]';\nconst SENSITIVE_AUTOCOMPLETE = /(^|\\s)(cc-csc|cc-exp|cc-exp-month|cc-exp-year|cc-number|current-password|new-password|one-time-code)(\\s|$)/i;\nconst SENSITIVE_NAME_PARTS = ['card', 'credit', 'cvc', 'cvv', 'iban', 'pin', 'secret', 'ssn', 'token'];\nconst MODIFIER_KEYS = new Set(['Alt', 'AltGraph', 'Control', 'Meta', 'OS', 'Shift']);\nconst ERROR_DEDUPE_MS = 1000;\n\n/** The window members the journey capture listens on. */\nexport type LtJourneyCaptureWindow = Pick<Window, 'addEventListener' | 'location' | 'removeEventListener' | 'scrollY'> & {\n document?: Document;\n MutationObserver?: typeof MutationObserver;\n};\n\n/**\n * Whether a form field holds secrets: password fields, hidden fields, `autocomplete` `current-password` /\n * `new-password` / `one-time-code` / `cc-*`, and names or ids like tokens, secrets, PINs or card numbers. Values of such\n * fields are never recorded, not even with `captureInputValues`.\n */\nexport function isLtSensitiveField(element: Element | null | undefined): boolean {\n if (!element || typeof element.getAttribute !== 'function') {\n return false;\n }\n const tag = element.tagName.toLowerCase();\n if (tag !== 'input' && tag !== 'textarea' && tag !== 'select' && !(element as HTMLElement).isContentEditable) {\n return false;\n }\n const type = (element.getAttribute('type') ?? '').toLowerCase();\n if (tag === 'input' && (type === 'password' || type === 'hidden')) {\n return true;\n }\n if (SENSITIVE_AUTOCOMPLETE.test(element.getAttribute('autocomplete') ?? '')) {\n return true;\n }\n return [element.getAttribute('name') ?? '', element.id ?? ''].some(\n (name) => !!name && (isLtSensitiveKey(name) || SENSITIVE_NAME_PARTS.some((part) => name.toLowerCase().includes(part))),\n );\n}\n\n/**\n * Records the user journey in a ring buffer: clicks, navigation, form submit/change, (optional) typing, hover and\n * scroll, keyboard shortcuts, errors and dialogs. Never recorded: typed text, values of sensitive fields (see\n * {@link isLtSensitiveField}), values at all without `captureInputValues`, and interactions inside the reporter's own UI\n * ({@link LT_BUG_UI_ATTRIBUTE}). URLs and texts are redacted.\n */\nexport class LtJourneyCapture {\n private readonly buffer: LtRingBuffer<LtUserInteractionEvent>;\n private readonly cleanups: (() => void)[] = [];\n private lastUrl: string | null = null;\n private lastError: { at: number; message: string } | null = null;\n private view: LtJourneyCaptureWindow | null = null;\n\n constructor(private readonly options: Required<LtBugUserJourneyOptions>) {\n this.buffer = new LtRingBuffer(options.maxEvents);\n }\n\n /** Whether the listeners are attached. */\n get installed(): boolean {\n return this.view !== null;\n }\n\n /**\n * Attach the listeners (idempotent). `listenToHistory` adds `popstate`/`hashchange` listeners for apps without the\n * Angular router; with a router call {@link recordNavigation} from its `NavigationEnd` events instead.\n */\n install(view: LtJourneyCaptureWindow, options: { listenToHistory: boolean }): void {\n if (this.view || !this.options.enabled) {\n return;\n }\n this.view = view;\n const o = this.options;\n const listen = (target: Pick<Window, 'addEventListener' | 'removeEventListener'>, type: string, handler: EventListener, capture = true) => {\n const listenerOptions: AddEventListenerOptions = { capture, passive: true };\n target.addEventListener(type, handler, listenerOptions);\n this.cleanups.push(() => target.removeEventListener(type, handler, listenerOptions));\n };\n\n if (o.captureClicks) {\n listen(view, 'click', (event) => {\n const element = this.eventElement(event, INTERACTIVE);\n if (element) {\n const description = describe(element);\n this.record('click', description.target, description);\n }\n });\n }\n if (o.captureNavigation) {\n this.recordNavigation(view.location?.href ?? '');\n if (options.listenToHistory) {\n const onHistory = () => this.recordNavigation(view.location?.href ?? '');\n listen(view, 'popstate', onHistory, false);\n listen(view, 'hashchange', onHistory, false);\n }\n }\n if (o.captureFormInteractions) {\n listen(view, 'submit', (event) => {\n const element = this.eventElement(event);\n if (element) {\n const description = describe(element);\n this.record('form_submit', description.target, description);\n }\n });\n listen(view, 'change', (event) => this.recordField('form_change', event));\n }\n if (o.captureInputChanges) {\n listen(\n view,\n 'input',\n this.throttle((event: Event) => this.recordField('input_change', event)),\n );\n }\n if (o.captureHover) {\n listen(\n view,\n 'mouseover',\n this.throttle((event: Event) => {\n const element = this.eventElement(event, INTERACTIVE);\n if (element) {\n const description = describe(element);\n this.record('hover', description.target, description);\n }\n }),\n );\n }\n if (o.captureScroll) {\n listen(\n view,\n 'scroll',\n this.throttle(() => this.record('scroll', 'window', { scrollPosition: Math.round(view.scrollY || view.document?.documentElement?.scrollTop || 0) })),\n false,\n );\n }\n if (o.captureKeyboard) {\n listen(view, 'keydown', (event) => this.recordKey(event as KeyboardEvent), false);\n }\n if (o.captureErrors) {\n listen(\n view,\n 'error',\n (event) => {\n const error = event as ErrorEvent;\n if (error.message || error.error) {\n this.recordError(error.error instanceof Error ? error.error.message : error.message, error.filename);\n }\n },\n false,\n );\n listen(view, 'unhandledrejection', (event) => this.recordError(reasonMessage((event as PromiseRejectionEvent).reason)), false);\n }\n if (o.captureModalEvents) {\n this.observeDialogs(view);\n }\n }\n\n /** Remove every listener and pending throttle timer. */\n uninstall(): void {\n while (this.cleanups.length) {\n this.cleanups.pop()?.();\n }\n this.view = null;\n this.lastUrl = null;\n }\n\n /** Record an interaction (also for custom events of the app); ignored while the journey is disabled. */\n record(type: LtUserInteractionType, target: string, metadata?: LtUserInteractionMetadata): void {\n if (!this.options.enabled) {\n return;\n }\n this.buffer.push({ metadata, target: truncateLt(redactLtText(target), 200), timestamp: new Date().toISOString(), type });\n }\n\n /** Record a navigation to `url` (skipped when it equals the last recorded URL). */\n recordNavigation(url: string): void {\n if (!this.options.captureNavigation || !url || url === this.lastUrl) {\n return;\n }\n const fromUrl = this.lastUrl;\n this.lastUrl = url;\n const toUrl = redactLtUrl(url);\n this.record('navigation', toUrl, { ...(fromUrl ? { fromUrl: redactLtUrl(fromUrl) } : {}), toUrl, url: toUrl });\n }\n\n /** Record an error (the same message within a second is recorded once). */\n recordError(message: string, source?: string): void {\n if (!this.options.captureErrors) {\n return;\n }\n const at = Date.now();\n if (this.lastError && this.lastError.message === message && at - this.lastError.at < ERROR_DEDUPE_MS) {\n return;\n }\n this.lastError = { at, message };\n this.record('error', 'window', { errorMessage: truncateLt(redactLtText(message || 'Error'), 500), ...(source ? { url: redactLtUrl(source) } : {}) });\n }\n\n /** The newest `limit` events, oldest first. */\n entries(limit?: number): LtUserInteractionEvent[] {\n return this.buffer.toArray(limit);\n }\n\n /** Number of stored events. */\n get size(): number {\n return this.buffer.size;\n }\n\n /** Remove every event. */\n clear(): void {\n this.buffer.clear();\n }\n\n private recordField(type: 'form_change' | 'input_change', event: Event): void {\n const element = this.eventElement(event);\n if (!element || !['input', 'select', 'textarea'].includes(element.tagName.toLowerCase())) {\n return;\n }\n if (type === 'input_change' && element.tagName.toLowerCase() === 'select') {\n return;\n }\n const description = describe(element);\n let value: string | undefined;\n if (this.options.captureInputValues && !isLtSensitiveField(element)) {\n const raw = (element as HTMLInputElement).value;\n value = typeof raw === 'string' && raw ? truncateLt(redactLtText(raw.slice(0, 200)), 50) : undefined;\n }\n this.record(type, description.target, { ...description, ...(value ? { value } : {}) });\n }\n\n private recordKey(event: KeyboardEvent): void {\n if (!(event.ctrlKey || event.metaKey || event.altKey) || MODIFIER_KEYS.has(event.key)) {\n return;\n }\n // Option (macOS) and AltGr (Windows: Ctrl+Alt) produce typed characters ('@', '€', '{' …): never record those.\n if (event.altKey && event.key.length === 1) {\n return;\n }\n const target = event.target as Element | null;\n if (target && typeof target.closest === 'function') {\n if (target.closest(`[${LT_BUG_UI_ATTRIBUTE}]`)) {\n return;\n }\n const editable = isEditable(target);\n if (editable && (isLtSensitiveField(target) || event.altKey || !(event.ctrlKey || event.metaKey))) {\n return;\n }\n }\n this.record('keyboard', event.key, { altKey: event.altKey, ctrlKey: event.ctrlKey, key: event.key, metaKey: event.metaKey, shiftKey: event.shiftKey });\n }\n\n /** The element an event refers to (optionally the closest match of `selector`), `null` inside the reporter's UI. */\n private eventElement(event: Event, selector?: string): Element | null {\n const target = event.target as Element | null;\n if (!target || typeof target.closest !== 'function' || target.closest(`[${LT_BUG_UI_ATTRIBUTE}]`)) {\n return null;\n }\n return (selector ? target.closest(selector) : null) ?? target;\n }\n\n private observeDialogs(view: LtJourneyCaptureWindow): void {\n const Observer = view.MutationObserver;\n const body = view.document?.body;\n if (!Observer || !body) {\n return;\n }\n const open = new Set<Element>();\n const dialogsIn = (node: Node): Element[] => {\n if (node.nodeType !== 1) {\n return [];\n }\n const element = node as Element;\n const found = element.matches(DIALOG) ? [element] : [];\n return [...found, ...Array.from(element.querySelectorAll(DIALOG))].filter((dialog) => !dialog.closest(`[${LT_BUG_UI_ATTRIBUTE}]`));\n };\n const observer = new Observer((mutations) => {\n for (const mutation of mutations) {\n mutation.addedNodes.forEach((node) =>\n dialogsIn(node).forEach((dialog) => {\n if (!open.has(dialog)) {\n open.add(dialog);\n this.record('modal_open', dialogLabel(dialog), { tag: dialog.tagName.toLowerCase() });\n }\n }),\n );\n mutation.removedNodes.forEach((node) =>\n dialogsIn(node).forEach((dialog) => {\n if (open.delete(dialog)) {\n this.record('modal_close', dialogLabel(dialog), { tag: dialog.tagName.toLowerCase() });\n }\n }),\n );\n }\n });\n observer.observe(body, { childList: true, subtree: true });\n this.cleanups.push(() => observer.disconnect());\n }\n\n /** Leading and trailing throttle of high-frequency events (`throttleRate`). */\n private throttle(handler: (event: Event) => void): EventListener {\n const delay = this.options.throttleRate;\n let last = 0;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let pending: Event | null = null;\n this.cleanups.push(() => {\n if (timer) {\n clearTimeout(timer);\n }\n });\n return (event: Event) => {\n const now = Date.now();\n if (now - last >= delay) {\n last = now;\n handler(event);\n return;\n }\n pending = event;\n timer ??= setTimeout(\n () => {\n timer = null;\n last = Date.now();\n if (pending) {\n handler(pending);\n pending = null;\n }\n },\n delay - (now - last),\n );\n };\n }\n}\n\nfunction describe(element: Element): LtUserInteractionMetadata & { target: string } {\n const tag = element.tagName.toLowerCase();\n const id = element.id || undefined;\n const classes = element.classList?.length ? Array.from(element.classList).slice(0, 10) : undefined;\n const ownText = (element.textContent ?? '').replace(/\\s+/g, ' ').trim().slice(0, 50);\n const label = element.getAttribute('aria-label') ?? element.getAttribute('title') ?? '';\n const text = ownText || label ? redactLtText(ownText || label) : undefined;\n let target = tag;\n if (id) {\n target += `#${id}`;\n }\n if (classes?.length) {\n target += `.${classes.slice(0, 3).join('.')}`;\n }\n target = truncateLt(target, 120);\n return { classes, element: target, id, tag, target, text };\n}\n\nfunction dialogLabel(dialog: Element): string {\n const labelledBy = dialog.getAttribute('aria-labelledby');\n const labelled = labelledBy ? dialog.ownerDocument?.getElementById(labelledBy.split(/\\s+/)[0] ?? '')?.textContent : null;\n const label = (dialog.getAttribute('aria-label') ?? labelled ?? dialog.querySelector('h1,h2,h3')?.textContent ?? dialog.tagName.toLowerCase()).replace(/\\s+/g, ' ').trim();\n return truncateLt(redactLtText(label), 80);\n}\n\nfunction isEditable(element: Element): boolean {\n const tag = element.tagName.toLowerCase();\n return tag === 'input' || tag === 'textarea' || tag === 'select' || !!(element as HTMLElement).isContentEditable;\n}\n\nfunction reasonMessage(reason: unknown): string {\n return reason instanceof Error ? reason.message : typeof reason === 'string' ? reason : String(reason);\n}\n","import type { LtNetworkRequestEntry } from './bug-types';\nimport { isLtBodyExcludedUrl, redactLtBody, redactLtHeaders, redactLtText, redactLtUrl } from './redact';\nimport { LtRingBuffer } from './ring-buffer';\n\nconst STATIC_EXTENSIONS = ['.css', '.eot', '.gif', '.ico', '.jpeg', '.jpg', '.js', '.map', '.mjs', '.png', '.svg', '.ttf', '.webp', '.woff', '.woff2'];\nconst MAX_RESPONSE_BYTES = 1_000_000;\n\n/** The window members the network capture patches. */\nexport type LtNetworkCaptureWindow = Pick<Window, 'fetch' | 'location'> & { XMLHttpRequest?: typeof XMLHttpRequest };\n\ninterface XhrInfo {\n capture: boolean;\n headers: Record<string, string>;\n method: string;\n url: string;\n}\n\ntype XhrOpen = (this: XMLHttpRequest, method: string, url: string | URL, ...rest: unknown[]) => void;\ntype XhrSend = (this: XMLHttpRequest, body?: Document | XMLHttpRequestBodyInit | null) => void;\ntype XhrSetRequestHeader = (this: XMLHttpRequest, name: string, value: string) => void;\n\n/**\n * Wraps `fetch` and `XMLHttpRequest` and records method, redacted URL, status, duration and redacted headers in a ring\n * buffer. Never recorded: values of `Authorization`, `Cookie`, `Set-Cookie`, `X-System-Setup-Token` and similar headers\n * (`[redacted]`), bodies of auth endpoints (`/iam/`, `/system-setup/`, … see `isLtBodyExcludedUrl`), streams\n * (`text/event-stream`), binary bodies and responses above 1 MB. Other bodies are redacted and cut to 1000 characters.\n * Static assets and the paths in `ignorePaths` (the report endpoint) are skipped. The response is handed to the caller\n * unchanged and without waiting for the body.\n */\nexport class LtNetworkCapture {\n /** While `true` (screenshot capture), requests are not recorded. */\n paused = false;\n\n private readonly buffer: LtRingBuffer<LtNetworkRequestEntry>;\n private restore: (() => void) | null = null;\n\n constructor(\n capacity: number,\n private readonly ignorePaths: readonly string[] = [],\n ) {\n this.buffer = new LtRingBuffer(capacity);\n }\n\n /** Whether `fetch` / `XMLHttpRequest` are currently wrapped. */\n get installed(): boolean {\n return this.restore !== null;\n }\n\n /** Wrap `view.fetch` and `view.XMLHttpRequest.prototype` (idempotent). */\n install(view: LtNetworkCaptureWindow): void {\n if (this.restore) {\n return;\n }\n const restorers: (() => void)[] = [];\n if (typeof view.fetch === 'function') {\n restorers.push(this.wrapFetch(view));\n }\n const proto = view.XMLHttpRequest?.prototype;\n if (proto && typeof proto.open === 'function' && typeof proto.send === 'function') {\n restorers.push(this.wrapXhr(view, proto));\n }\n this.restore = () => restorers.forEach((restore) => restore());\n }\n\n /** Restore the original `fetch` / `XMLHttpRequest` methods (only those still wrapped by this instance). */\n uninstall(): void {\n this.restore?.();\n this.restore = null;\n }\n\n /** The newest `limit` entries, oldest first. */\n entries(limit?: number): LtNetworkRequestEntry[] {\n return this.buffer.toArray(limit);\n }\n\n /** Number of stored entries. */\n get size(): number {\n return this.buffer.size;\n }\n\n /** Remove every entry. */\n clear(): void {\n this.buffer.clear();\n }\n\n /** Whether a request to `url` is recorded (no static asset, no data/blob URL, not an ignored path). */\n shouldCapture(url: string, view: Pick<Window, 'location'>): boolean {\n if (this.paused || /^(data|blob):/i.test(url)) {\n return false;\n }\n let pathname: string;\n try {\n pathname = new URL(url, view.location?.href || 'http://localhost/').pathname;\n } catch {\n return true;\n }\n const lower = pathname.toLowerCase();\n if (STATIC_EXTENSIONS.some((extension) => lower.endsWith(extension))) {\n return false;\n }\n return !this.ignorePaths.some((path) => pathname === path || pathname.endsWith(path));\n }\n\n private wrapFetch(view: LtNetworkCaptureWindow): () => void {\n const originalFetch = view.fetch;\n const wrapped = async (...args: Parameters<typeof fetch>): Promise<Response> => {\n const [input, init] = args;\n const url = fetchUrl(input);\n if (!this.shouldCapture(url, view)) {\n return originalFetch.apply(view, args);\n }\n const request = isRequestLike(input) ? input : undefined;\n const method = String(init?.method ?? request?.method ?? 'GET').toUpperCase();\n const excludeBody = isLtBodyExcludedUrl(url);\n const requestHeaders = redactLtHeaders(headersToRecord(request?.headers, init?.headers));\n const requestBody = excludeBody ? undefined : bodyText(init?.body);\n const startTime = Date.now();\n try {\n const response = await originalFetch.apply(view, args);\n const entry: LtNetworkRequestEntry = {\n duration: Date.now() - startTime,\n method,\n requestBody,\n requestHeaders,\n responseHeaders: redactLtHeaders(headersToRecord(response.headers)),\n status: response.status,\n statusText: response.statusText,\n timestamp: new Date().toISOString(),\n type: 'fetch',\n url: redactLtUrl(url),\n };\n this.buffer.push(entry);\n if (!excludeBody) {\n readResponseBody(response, entry);\n }\n return response;\n } catch (error) {\n this.buffer.push({\n duration: Date.now() - startTime,\n error: redactLtText(error instanceof Error ? error.message : String(error)),\n method,\n requestBody,\n requestHeaders,\n status: 0,\n statusText: 'Network Error',\n timestamp: new Date().toISOString(),\n type: 'fetch',\n url: redactLtUrl(url),\n });\n throw error;\n }\n };\n view.fetch = wrapped as typeof fetch;\n return () => {\n if (view.fetch === (wrapped as typeof fetch)) {\n view.fetch = originalFetch;\n }\n };\n }\n\n private wrapXhr(view: LtNetworkCaptureWindow, proto: XMLHttpRequest): () => void {\n // Arrow functions keep the capture as `this`; the patched methods below get the XMLHttpRequest as `this`.\n const shouldCapture = (url: string) => this.shouldCapture(url, view);\n const isPaused = () => this.paused;\n const record = (entry: LtNetworkRequestEntry) => this.buffer.push(entry);\n const infos = new WeakMap<XMLHttpRequest, XhrInfo>();\n const originalOpen = proto.open as XhrOpen;\n const originalSend = proto.send as XhrSend;\n const originalSetRequestHeader = proto.setRequestHeader as XhrSetRequestHeader;\n\n const open: XhrOpen = function (method, url, ...rest) {\n const urlString = String(url);\n infos.set(this, { capture: shouldCapture(urlString), headers: {}, method: String(method).toUpperCase(), url: urlString });\n return originalOpen.call(this, method, url, ...rest);\n };\n const setRequestHeader: XhrSetRequestHeader = function (name, value) {\n const info = infos.get(this);\n if (info) {\n info.headers[name] = value;\n }\n return originalSetRequestHeader.call(this, name, value);\n };\n const send: XhrSend = function (body) {\n const info = infos.get(this);\n if (!info?.capture || isPaused()) {\n return originalSend.call(this, body);\n }\n const excludeBody = isLtBodyExcludedUrl(info.url);\n const requestBody = excludeBody ? undefined : bodyText(body);\n const startTime = Date.now();\n this.addEventListener(\n 'loadend',\n () => {\n const readable = this.responseType === '' || this.responseType === 'text';\n record({\n duration: Date.now() - startTime,\n ...(this.status === 0 ? { error: 'Network Error' } : {}),\n method: info.method,\n requestBody,\n requestHeaders: redactLtHeaders(info.headers),\n responseBody: !excludeBody && readable && this.responseText ? redactLtBody(this.responseText) : undefined,\n responseHeaders: redactLtHeaders(parseHeaderBlock(this.getAllResponseHeaders())),\n status: this.status,\n statusText: this.statusText,\n timestamp: new Date().toISOString(),\n type: 'xhr',\n url: redactLtUrl(info.url),\n });\n },\n { once: true },\n );\n return originalSend.call(this, body);\n };\n\n proto.open = open as XMLHttpRequest['open'];\n proto.send = send;\n proto.setRequestHeader = setRequestHeader;\n return () => {\n if (proto.open === (open as XMLHttpRequest['open'])) {\n proto.open = originalOpen as XMLHttpRequest['open'];\n }\n if (proto.send === send) {\n proto.send = originalSend;\n }\n if (proto.setRequestHeader === setRequestHeader) {\n proto.setRequestHeader = originalSetRequestHeader;\n }\n };\n }\n}\n\nfunction isRequestLike(input: unknown): input is Request {\n return typeof input === 'object' && input !== null && !(input instanceof URL) && typeof (input as Request).url === 'string';\n}\n\n/** URL of a `fetch()` call: string, `URL` (its `href`) or `Request` (its `url`). */\nfunction fetchUrl(input: RequestInfo | URL): string {\n if (typeof input === 'string') {\n return input;\n }\n if (input instanceof URL) {\n return input.href;\n }\n return isRequestLike(input) ? input.url : String(input ?? '');\n}\n\n/** Header map of a `Headers` object / init, later sources win. */\nfunction headersToRecord(...sources: (HeadersInit | Headers | null | undefined)[]): Record<string, string> {\n const result: Record<string, string> = {};\n for (const source of sources) {\n if (!source) {\n continue;\n }\n try {\n new Headers(source).forEach((value, name) => (result[name.toLowerCase()] = value));\n } catch {\n // Invalid header init: nothing to record.\n }\n }\n return result;\n}\n\n/** Recordable text of a request body (binary bodies, form data and streams only as a marker). */\nfunction bodyText(body: unknown): string | undefined {\n if (body === null || body === undefined) {\n return undefined;\n }\n if (typeof body === 'string') {\n return redactLtBody(body);\n }\n if (typeof URLSearchParams !== 'undefined' && body instanceof URLSearchParams) {\n return redactLtBody(body.toString());\n }\n if (typeof FormData !== 'undefined' && body instanceof FormData) {\n return '[FormData]';\n }\n if (typeof Blob !== 'undefined' && body instanceof Blob) {\n return `[Blob ${body.size} bytes]`;\n }\n if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {\n return `[binary ${(body as ArrayBuffer).byteLength} bytes]`;\n }\n return '[body not recorded]';\n}\n\n/** Read a textual response body in the background (the caller gets the response right away). */\nfunction readResponseBody(response: Response, entry: LtNetworkRequestEntry): void {\n const type = (response.headers.get('content-type') ?? '').toLowerCase();\n const length = Number(response.headers.get('content-length') ?? 0);\n const textual = !type || /json|text\\/|xml|javascript|x-www-form-urlencoded|graphql/.test(type);\n if (!textual || type.includes('event-stream') || length > MAX_RESPONSE_BYTES || response.bodyUsed) {\n return;\n }\n let clone: Response;\n try {\n clone = response.clone();\n } catch {\n return;\n }\n void clone.text().then(\n (text) => {\n if (text) {\n entry.responseBody = redactLtBody(text);\n }\n },\n () => undefined,\n );\n}\n\nfunction parseHeaderBlock(block: string | null): Record<string, string> {\n const result: Record<string, string> = {};\n for (const line of (block ?? '').split(/\\r?\\n/)) {\n const index = line.indexOf(':');\n if (index > 0) {\n result[line.slice(0, index).trim().toLowerCase()] = line.slice(index + 1).trim();\n }\n }\n return result;\n}\n","import type { ErrorHandler } from '@angular/core';\nimport { NavigationEnd, type Router } from '@angular/router';\n\nimport { getLtBrowserInfo } from './browser-info';\nimport type {\n LtBrowserInfo,\n LtBugAttachment,\n LtBugErrorInfo,\n LtBugReportData,\n LtConsoleLogEntry,\n LtNetworkRequestEntry,\n LtResolvedBugOptions,\n LtUserInteractionEvent,\n LtUserInteractionMetadata,\n LtUserInteractionType,\n} from './bug-types';\nimport { LtConsoleCapture } from './console-capture';\nimport { LtErrorCapture, toLtBugErrorInfo } from './error-capture';\nimport { LtJourneyCapture } from './journey-capture';\nimport { LtNetworkCapture } from './network-capture';\nimport { buildLtBugReport, type LtBugReportFormValue, type LtBugReportIncludes } from './report';\n\n/** What {@link startLtBugCapture} needs from the app. */\nexport interface LtBugCaptureDeps {\n /** Base URL for router URLs (`document.baseURI`). */\n baseUri: string;\n /** The app's `ErrorHandler` (wrapped, it keeps handling every error); `null` skips it. */\n errorHandler: ErrorHandler | null;\n /** Called once per captured error. */\n onError: (info: LtBugErrorInfo) => void;\n options: LtResolvedBugOptions;\n /** The app's router (navigation from `NavigationEnd`); without one `popstate`/`hashchange` are used. */\n router: Pick<Router, 'events'> | null;\n view: Window;\n}\n\n/** Handle of the installed capture hooks. */\nexport interface LtBugCaptureEngine {\n browserInfo(): LtBrowserInfo | null;\n buildReport(form: LtBugReportFormValue, attachments: readonly LtBugAttachment[], includes: LtBugReportIncludes): LtBugReportData;\n consoleLogs(): LtConsoleLogEntry[];\n networkRequests(): LtNetworkRequestEntry[];\n record(type: LtUserInteractionType, target: string, metadata?: LtUserInteractionMetadata): void;\n recordError(message: string): void;\n reportError(error: unknown, source?: string): void;\n setNetworkPaused(paused: boolean): void;\n stop(): void;\n userJourney(): LtUserInteractionEvent[];\n}\n\n/**\n * Install the capture hooks of the enabled features (console, `fetch`/`XMLHttpRequest`, user journey, `ErrorHandler`\n * and window errors). Loaded by `LtBugReportService.start()` only while the reporter is active, so production bundles\n * load none of this code.\n */\nexport function startLtBugCapture(deps: LtBugCaptureDeps): LtBugCaptureEngine {\n const { options, view } = deps;\n const consoleCapture = options.enableConsoleLogs ? new LtConsoleCapture(options.maxConsoleLogs, (view as Window & typeof globalThis).console ?? console) : null;\n consoleCapture?.install(view);\n\n const networkCapture = options.enableNetworkRequests ? new LtNetworkCapture(options.maxNetworkRequests, [options.endpoint]) : null;\n networkCapture?.install(view);\n\n const journeyEnabled = options.enableUserJourney && options.userJourney.enabled;\n const journeyCapture = journeyEnabled ? new LtJourneyCapture(options.userJourney) : null;\n journeyCapture?.install(view, { listenToHistory: !deps.router });\n const routerSubscription =\n journeyCapture && deps.router && options.userJourney.captureNavigation\n ? deps.router.events.subscribe((event) => {\n if (event instanceof NavigationEnd) {\n journeyCapture.recordNavigation(absoluteUrl(event.urlAfterRedirects, deps.baseUri || view.location.href));\n }\n })\n : null;\n\n const errorCapture = options.enableErrorBoundary\n ? new LtErrorCapture((info) => {\n journeyCapture?.recordError(info.message);\n deps.onError(info);\n })\n : null;\n errorCapture?.install(deps.errorHandler, view);\n\n const engine: LtBugCaptureEngine = {\n browserInfo: () => {\n try {\n return getLtBrowserInfo(view as Window & typeof globalThis);\n } catch {\n return null;\n }\n },\n buildReport: (form, attachments, includes) =>\n buildLtBugReport(form, attachments, includes, {\n browserInfo: options.enableBrowserInfo ? () => getLtBrowserInfo(view as Window & typeof globalThis) : undefined,\n consoleLogs: consoleCapture ? () => engine.consoleLogs() : undefined,\n networkRequests: networkCapture ? () => engine.networkRequests() : undefined,\n userInteractions: journeyCapture ? () => engine.userJourney() : undefined,\n }),\n consoleLogs: () => consoleCapture?.entries(options.maxConsoleLogs) ?? [],\n networkRequests: () => networkCapture?.entries(options.maxNetworkRequests) ?? [],\n record: (type, target, metadata) => journeyCapture?.record(type, target, metadata),\n recordError: (message) => journeyCapture?.recordError(message),\n reportError: (error, source) => (errorCapture ? errorCapture.report(error, source) : deps.onError(toLtBugErrorInfo(error, source, view))),\n setNetworkPaused: (paused) => {\n if (networkCapture) {\n networkCapture.paused = paused;\n }\n },\n stop: () => {\n consoleCapture?.uninstall();\n networkCapture?.uninstall();\n journeyCapture?.uninstall();\n errorCapture?.uninstall();\n routerSubscription?.unsubscribe();\n },\n userJourney: () => journeyCapture?.entries(options.userJourney.maxEvents) ?? [],\n };\n return engine;\n}\n\n/** Router URL (`/orders?x=1`) as absolute URL below the base href. */\nfunction absoluteUrl(routerUrl: string, base: string): string {\n try {\n return new URL(routerUrl.replace(/^\\//, ''), base).href;\n } catch {\n return routerUrl;\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lenne.tech-ng-base-bug-constants-Brm2KGHi.mjs","names":[],"sources":["../../../projects/ng-base/bug/src/lib/constants.ts"],"sourcesContent":["/** Attribute that marks the reporter's own UI (button, dialog): left out of the user journey and the screenshot. */\nexport const LT_BUG_UI_ATTRIBUTE = 'data-lt-bug-ui';\n"],"mappings":"AACA,MAAa,sBAAsB"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
const LT_BUG_MESSAGES = {
|
|
2
|
+
de: { lt: { "bug": {
|
|
3
|
+
"button": "Fehler melden",
|
|
4
|
+
"capturing": "Screenshot wird erstellt …",
|
|
5
|
+
"dialogTitle": "Fehler melden",
|
|
6
|
+
"dialogDescription": "Beschreiben Sie das Problem. Technische Informationen werden auf Wunsch automatisch angehängt.",
|
|
7
|
+
"title": "Titel",
|
|
8
|
+
"titlePlaceholder": "Kurze Beschreibung des Problems",
|
|
9
|
+
"titleRequired": "Titel ist erforderlich",
|
|
10
|
+
"type": "Typ",
|
|
11
|
+
"typePlaceholder": "Typ auswählen",
|
|
12
|
+
"typeRequired": "Typ ist erforderlich",
|
|
13
|
+
"types": {
|
|
14
|
+
"bug": "Bug",
|
|
15
|
+
"feature": "Feature",
|
|
16
|
+
"enhancement": "Verbesserung",
|
|
17
|
+
"other": "Sonstiges"
|
|
18
|
+
},
|
|
19
|
+
"description": "Beschreibung",
|
|
20
|
+
"descriptionPlaceholder": "Was ist passiert …",
|
|
21
|
+
"descriptionRequired": "Beschreibung ist erforderlich",
|
|
22
|
+
"expectedBehavior": "Erwartetes Verhalten",
|
|
23
|
+
"expectedBehaviorPlaceholder": "Was hätten Sie erwartet?",
|
|
24
|
+
"stepsToReproduce": "Schritte zur Reproduktion",
|
|
25
|
+
"stepsToReproducePlaceholder": "1. Gehe zu … 2. Klicke auf … 3. Fehler erscheint",
|
|
26
|
+
"attachments": "Anhänge",
|
|
27
|
+
"attachmentsCount": "Anhänge ({count})",
|
|
28
|
+
"screenshotCaptured": "(Screenshot automatisch erfasst)",
|
|
29
|
+
"screenshot": "Screenshot",
|
|
30
|
+
"selectFiles": "Dateien hochladen",
|
|
31
|
+
"dropHint": "oder hier hineinziehen",
|
|
32
|
+
"maxFileSize": "Max. {max} MB pro Datei",
|
|
33
|
+
"removeAttachment": "Entfernen: {name}",
|
|
34
|
+
"fileTooLarge": "{name} ist zu groß (höchstens {max} MB)",
|
|
35
|
+
"tooManyFiles": "{name} wurde nicht hinzugefügt: höchstens {max} Anhänge",
|
|
36
|
+
"fileReadFailed": "{name} konnte nicht gelesen werden",
|
|
37
|
+
"additionalInfo": "Zusätzliche Informationen",
|
|
38
|
+
"browserInfo": "Browser-Informationen auslesen",
|
|
39
|
+
"browserInfoHint": "Browser, Betriebssystem, Bildschirmgröße, etc.",
|
|
40
|
+
"consoleLogs": "Konsolen-Logs auslesen",
|
|
41
|
+
"consoleLogsHint": "Aktuelle Browser-Konsolennachrichten ({count})",
|
|
42
|
+
"networkRequests": "Netzwerk-Anfragen auslesen",
|
|
43
|
+
"networkRequestsHint": "API-Calls und HTTP-Requests der letzten Minuten ({count})",
|
|
44
|
+
"userJourney": "User Journey auslesen",
|
|
45
|
+
"userJourneyHint": "Benutzer-Interaktionen und Navigation ({count} Events)",
|
|
46
|
+
"journeyPreview": "User Journey Preview ({count} Events)",
|
|
47
|
+
"journeyFilter": "Event-Typ",
|
|
48
|
+
"allEventTypes": "Alle Event-Typen",
|
|
49
|
+
"journeyEmpty": "Keine User Journey Events aufgezeichnet",
|
|
50
|
+
"journeyEvents": "User Journey",
|
|
51
|
+
"events": {
|
|
52
|
+
"click": "Klick",
|
|
53
|
+
"navigation": "Navigation",
|
|
54
|
+
"form_submit": "Formular gesendet",
|
|
55
|
+
"form_change": "Formular geändert",
|
|
56
|
+
"input_change": "Eingabe",
|
|
57
|
+
"hover": "Hover",
|
|
58
|
+
"scroll": "Scrollen",
|
|
59
|
+
"keyboard": "Tastatur",
|
|
60
|
+
"modal_open": "Dialog geöffnet",
|
|
61
|
+
"modal_close": "Dialog geschlossen",
|
|
62
|
+
"error": "Fehler"
|
|
63
|
+
},
|
|
64
|
+
"metaText": "Text",
|
|
65
|
+
"metaValue": "Wert",
|
|
66
|
+
"metaUrl": "URL",
|
|
67
|
+
"metaPosition": "Position",
|
|
68
|
+
"metaKey": "Taste",
|
|
69
|
+
"metaError": "Fehler",
|
|
70
|
+
"cancel": "Abbrechen",
|
|
71
|
+
"submit": "Senden",
|
|
72
|
+
"submitting": "Wird gesendet …",
|
|
73
|
+
"dismissError": "Fehler ausblenden",
|
|
74
|
+
"successTitle": "Fehlerbericht gesendet",
|
|
75
|
+
"successDescription": "Ticket {identifier} wurde angelegt.",
|
|
76
|
+
"errorTitle": "Fehlerbericht konnte nicht gesendet werden",
|
|
77
|
+
"errorSubmit": "Bitte versuchen Sie es später erneut.",
|
|
78
|
+
"errorInvalid": "Der Bericht ist unvollständig. Bitte prüfen Sie Titel, Typ und Beschreibung.",
|
|
79
|
+
"errorUnavailable": "Fehlermeldungen sind auf diesem Server nicht aktiviert.",
|
|
80
|
+
"errorTooLarge": "Der Bericht ist zu groß. Entfernen Sie Anhänge und versuchen Sie es erneut.",
|
|
81
|
+
"errorRateLimited": "Zu viele Berichte in kurzer Zeit. Bitte warten Sie einen Moment."
|
|
82
|
+
} } },
|
|
83
|
+
en: { lt: { "bug": {
|
|
84
|
+
"button": "Report a bug",
|
|
85
|
+
"capturing": "Taking screenshot …",
|
|
86
|
+
"dialogTitle": "Report a bug",
|
|
87
|
+
"dialogDescription": "Describe the problem. Technical details are attached automatically if you want.",
|
|
88
|
+
"title": "Title",
|
|
89
|
+
"titlePlaceholder": "Short summary of the problem",
|
|
90
|
+
"titleRequired": "Title is required",
|
|
91
|
+
"type": "Type",
|
|
92
|
+
"typePlaceholder": "Select a type",
|
|
93
|
+
"typeRequired": "Type is required",
|
|
94
|
+
"types": {
|
|
95
|
+
"bug": "Bug",
|
|
96
|
+
"feature": "Feature",
|
|
97
|
+
"enhancement": "Enhancement",
|
|
98
|
+
"other": "Other"
|
|
99
|
+
},
|
|
100
|
+
"description": "Description",
|
|
101
|
+
"descriptionPlaceholder": "What happened …",
|
|
102
|
+
"descriptionRequired": "Description is required",
|
|
103
|
+
"expectedBehavior": "Expected behavior",
|
|
104
|
+
"expectedBehaviorPlaceholder": "What did you expect?",
|
|
105
|
+
"stepsToReproduce": "Steps to reproduce",
|
|
106
|
+
"stepsToReproducePlaceholder": "1. Go to … 2. Click … 3. The error appears",
|
|
107
|
+
"attachments": "Attachments",
|
|
108
|
+
"attachmentsCount": "Attachments ({count})",
|
|
109
|
+
"screenshotCaptured": "(screenshot taken automatically)",
|
|
110
|
+
"screenshot": "Screenshot",
|
|
111
|
+
"selectFiles": "Upload files",
|
|
112
|
+
"dropHint": "or drop them here",
|
|
113
|
+
"maxFileSize": "Max. {max} MB per file",
|
|
114
|
+
"removeAttachment": "Remove: {name}",
|
|
115
|
+
"fileTooLarge": "{name} is too large (at most {max} MB)",
|
|
116
|
+
"tooManyFiles": "{name} was not added: at most {max} attachments",
|
|
117
|
+
"fileReadFailed": "{name} could not be read",
|
|
118
|
+
"additionalInfo": "Additional information",
|
|
119
|
+
"browserInfo": "Include browser information",
|
|
120
|
+
"browserInfoHint": "Browser, operating system, screen size, etc.",
|
|
121
|
+
"consoleLogs": "Include console logs",
|
|
122
|
+
"consoleLogsHint": "Recent browser console messages ({count})",
|
|
123
|
+
"networkRequests": "Include network requests",
|
|
124
|
+
"networkRequestsHint": "API calls and HTTP requests of the last minutes ({count})",
|
|
125
|
+
"userJourney": "Include user journey",
|
|
126
|
+
"userJourneyHint": "User interactions and navigation ({count} events)",
|
|
127
|
+
"journeyPreview": "User journey preview ({count} events)",
|
|
128
|
+
"journeyFilter": "Event type",
|
|
129
|
+
"allEventTypes": "All event types",
|
|
130
|
+
"journeyEmpty": "No user journey events recorded",
|
|
131
|
+
"journeyEvents": "User journey",
|
|
132
|
+
"events": {
|
|
133
|
+
"click": "Click",
|
|
134
|
+
"navigation": "Navigation",
|
|
135
|
+
"form_submit": "Form submitted",
|
|
136
|
+
"form_change": "Form changed",
|
|
137
|
+
"input_change": "Input",
|
|
138
|
+
"hover": "Hover",
|
|
139
|
+
"scroll": "Scroll",
|
|
140
|
+
"keyboard": "Keyboard",
|
|
141
|
+
"modal_open": "Dialog opened",
|
|
142
|
+
"modal_close": "Dialog closed",
|
|
143
|
+
"error": "Error"
|
|
144
|
+
},
|
|
145
|
+
"metaText": "Text",
|
|
146
|
+
"metaValue": "Value",
|
|
147
|
+
"metaUrl": "URL",
|
|
148
|
+
"metaPosition": "Position",
|
|
149
|
+
"metaKey": "Key",
|
|
150
|
+
"metaError": "Error",
|
|
151
|
+
"cancel": "Cancel",
|
|
152
|
+
"submit": "Send",
|
|
153
|
+
"submitting": "Sending …",
|
|
154
|
+
"dismissError": "Dismiss error",
|
|
155
|
+
"successTitle": "Bug report sent",
|
|
156
|
+
"successDescription": "Ticket {identifier} was created.",
|
|
157
|
+
"errorTitle": "The bug report could not be sent",
|
|
158
|
+
"errorSubmit": "Please try again later.",
|
|
159
|
+
"errorInvalid": "The report is incomplete. Please check title, type and description.",
|
|
160
|
+
"errorUnavailable": "Bug reporting is not enabled on this server.",
|
|
161
|
+
"errorTooLarge": "The report is too large. Remove attachments and try again.",
|
|
162
|
+
"errorRateLimited": "Too many reports in a short time. Please wait a moment."
|
|
163
|
+
} } }
|
|
164
|
+
};
|
|
165
|
+
function registerLtBugMessages(i18n, appMessages = {}) {
|
|
166
|
+
for (const [locale, messages] of Object.entries(LT_BUG_MESSAGES)) i18n.registerMessages(locale, ltMergeMessages(messages, appMessages[locale]));
|
|
167
|
+
}
|
|
168
|
+
function ltMergeMessages(base, override) {
|
|
169
|
+
if (!override) return base;
|
|
170
|
+
const result = { ...base };
|
|
171
|
+
for (const [key, value] of Object.entries(override)) {
|
|
172
|
+
const current = result[key];
|
|
173
|
+
result[key] = typeof value === "object" && typeof current === "object" ? ltMergeMessages(current, value) : value;
|
|
174
|
+
}
|
|
175
|
+
return result;
|
|
176
|
+
}
|
|
177
|
+
export { LT_BUG_MESSAGES, ltMergeMessages, registerLtBugMessages };
|
|
178
|
+
|
|
179
|
+
//# sourceMappingURL=lenne.tech-ng-base-bug-messages-BsP4fRQU.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lenne.tech-ng-base-bug-messages-BsP4fRQU.mjs","names":[],"sources":["../tmp-esm2022/bug/lib/i18n/de.json","../tmp-esm2022/bug/lib/i18n/en.json","../../../projects/ng-base/bug/src/lib/i18n/messages.ts"],"sourcesContent":["","","import type { LtI18nMessages, LtI18nService } from '@lenne.tech/ng-base';\n\nimport de from './de.json';\nimport en from './en.json';\n\n/** The bug reporter's texts (`lt.bug.*`), shipped as `@lenne.tech/ng-base/i18n/bug/{de,en}.json` as well. */\nexport const LT_BUG_MESSAGES: Readonly<Record<'de' | 'en', LtI18nMessages>> = { de, en };\n\n/**\n * Register the bug reporter's texts with `LtI18nService` (merged; registering twice is harmless). Texts the app passed\n * in `provideLtNgBase({ i18n: { messages } })` keep priority, and an `LT_I18N_ADAPTER` still wins over both.\n *\n * Lives in the lazily loaded part (imported by the dialog and by `loadLtBugMessages()`), so the texts stay out of the\n * initial bundle.\n */\nexport function registerLtBugMessages(i18n: LtI18nService, appMessages: Record<string, LtI18nMessages> = {}): void {\n for (const [locale, messages] of Object.entries(LT_BUG_MESSAGES)) {\n i18n.registerMessages(locale, ltMergeMessages(messages, appMessages[locale]));\n }\n}\n\n/** Deep merge of message trees; `override` wins. */\nexport function ltMergeMessages(base: LtI18nMessages, override: LtI18nMessages | undefined): LtI18nMessages {\n if (!override) {\n return base;\n }\n const result: LtI18nMessages = { ...base };\n for (const [key, value] of Object.entries(override)) {\n const current = result[key];\n result[key] = typeof value === 'object' && typeof current === 'object' ? ltMergeMessages(current, value) : value;\n }\n return result;\n}\n"],"mappings":"AEMA,MAAa,kBAAiE;CAAE,IAAA,E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;C,IAAA;CAAI,IAAA,E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;C,IAAA;AAAE;AAStF,SAAgB,sBAAsB,MAAqB,cAA8C,CAAA,GAAE;CACzG,KAAK,MAAM,CAAC,QAAQ,aAAa,OAAO,QAAQ,eAAe,GAC7D,KAAK,iBAAiB,QAAQ,gBAAgB,UAAU,YAAY,OAAO,CAAC;AAEhF;AAGA,SAAgB,gBAAgB,MAAsB,UAAoC;CACxF,IAAI,CAAC,UACH,OAAO;CAET,MAAM,SAAyB,EAAE,GAAG,KAAI;CACxC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,GAAG;EACnD,MAAM,UAAU,OAAO;EACvB,OAAO,OAAO,OAAO,UAAU,YAAY,OAAO,YAAY,WAAW,gBAAgB,SAAS,KAAK,IAAI;CAC7G;CACA,OAAO;AACT"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { InjectionToken, inject, isDevMode, makeEnvironmentProviders } from "@angular/core";
|
|
2
|
+
import { LT_RUNTIME_CONFIG } from "@lenne.tech/ng-base";
|
|
3
|
+
const LT_BUG_INPUT_OPTIONS = new InjectionToken("LT_BUG_INPUT_OPTIONS", { factory: () => null });
|
|
4
|
+
const LT_BUG_DEV_MODE = new InjectionToken("LT_BUG_DEV_MODE", { factory: () => isDevMode() });
|
|
5
|
+
const LT_BUG_ACTIVE = new InjectionToken("LT_BUG_ACTIVE", { factory: () => {
|
|
6
|
+
const options = inject(LT_BUG_INPUT_OPTIONS);
|
|
7
|
+
if (options === null) return false;
|
|
8
|
+
const runtime = inject(LT_RUNTIME_CONFIG, { optional: true });
|
|
9
|
+
const runtimeEnabled = runtime?.lt?.["bug"]?.enabled;
|
|
10
|
+
return isLtBugActive({ enabled: typeof runtimeEnabled === "boolean" ? runtimeEnabled : options.enabled }, runtime?.appEnv, inject(LT_BUG_DEV_MODE));
|
|
11
|
+
} });
|
|
12
|
+
function isLtBugActive(options, appEnv, devMode) {
|
|
13
|
+
if (typeof options.enabled === "boolean") return options.enabled;
|
|
14
|
+
const env = typeof appEnv === "string" ? appEnv.trim().toLowerCase() : "";
|
|
15
|
+
if (!env) return devMode;
|
|
16
|
+
return env !== "production" && env !== "prod";
|
|
17
|
+
}
|
|
18
|
+
function provideLtBug(options = {}) {
|
|
19
|
+
return makeEnvironmentProviders([{
|
|
20
|
+
provide: LT_BUG_INPUT_OPTIONS,
|
|
21
|
+
useValue: options
|
|
22
|
+
}]);
|
|
23
|
+
}
|
|
24
|
+
export { LT_BUG_ACTIVE, LT_BUG_DEV_MODE, LT_BUG_INPUT_OPTIONS, isLtBugActive, provideLtBug };
|
|
25
|
+
|
|
26
|
+
//# sourceMappingURL=lenne.tech-ng-base-bug-provide.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lenne.tech-ng-base-bug-provide.mjs","names":[],"sources":["../../../projects/ng-base/bug/provide/src/lib/bug-options.ts","../../../projects/ng-base/bug/provide/src/lib/provide-lt-bug.ts"],"sourcesContent":["import { inject, InjectionToken, isDevMode } from '@angular/core';\nimport { LT_RUNTIME_CONFIG } from '@lenne.tech/ng-base';\n\nimport type { LtBugOptions } from './bug-types';\n\n/** Options passed to `provideLtBug()`; `null` when the provider is missing (the reporter stays off). */\nexport const LT_BUG_INPUT_OPTIONS = new InjectionToken<LtBugOptions | null>('LT_BUG_INPUT_OPTIONS', { factory: () => null });\n\n/** Dev mode flag used for the fail-closed decision (a token so tests can simulate a production build). */\nexport const LT_BUG_DEV_MODE = new InjectionToken<boolean>('LT_BUG_DEV_MODE', { factory: () => isDevMode() });\n\n/**\n * Whether the bug reporter is on in this app and stage: `provideLtBug()` is present and the runtime decision\n * ({@link isLtBugActive}) says on. The same on the server and in the browser (no hydration mismatch), so the app\n * shell can keep the reporter's chunk out of production entirely:\n *\n * @example app.html\n * @if (bugActive) { @defer (on immediate) { <lt-bug-report /> } }\n */\nexport const LT_BUG_ACTIVE = new InjectionToken<boolean>('LT_BUG_ACTIVE', {\n factory: () => {\n const options = inject(LT_BUG_INPUT_OPTIONS);\n if (options === null) {\n return false;\n }\n // Only `enabled` matters here (runtime `lt.bug.enabled` over the code option), so the defaults and the option\n // resolution stay in the lazy `@lenne.tech/ng-base/bug`.\n const runtime = inject(LT_RUNTIME_CONFIG, { optional: true });\n const runtimeEnabled = (runtime?.lt?.['bug'] as { enabled?: unknown } | undefined)?.enabled;\n const enabled = typeof runtimeEnabled === 'boolean' ? runtimeEnabled : options.enabled;\n return isLtBugActive({ enabled }, runtime?.appEnv, inject(LT_BUG_DEV_MODE));\n },\n});\n\n/**\n * Whether the reporter is active (decided at runtime, so one build serves every stage):\n *\n * 1. `enabled` set explicitly wins.\n * 2. App env (`NG_PUBLIC_APP_ENV`) `production` / `prod` → off, any other value → on.\n * 3. No app env → only in dev mode (`isDevMode()`): a production build without the variable fails closed.\n */\nexport function isLtBugActive(options: Pick<LtBugOptions, 'enabled'>, appEnv: unknown, devMode: boolean): boolean {\n if (typeof options.enabled === 'boolean') {\n return options.enabled;\n }\n const env = typeof appEnv === 'string' ? appEnv.trim().toLowerCase() : '';\n if (!env) {\n return devMode;\n }\n return env !== 'production' && env !== 'prod';\n}\n","import { makeEnvironmentProviders, type EnvironmentProviders } from '@angular/core';\n\nimport { LT_BUG_INPUT_OPTIONS } from './bug-options';\nimport type { LtBugOptions } from './bug-types';\n\n/**\n * Opt-in bug reporter (the Angular counterpart of the `@lenne.tech/bug.lt` Nuxt module): captures console output,\n * `fetch`/`XMLHttpRequest` calls, the user journey and errors, and lets the user send a report with screenshot to\n * Linear through `ltBugReport()` from `@lenne.tech/ng-base/bug/server`.\n *\n * Active only when the app env (`LT_RUNTIME_CONFIG.appEnv`, `NG_PUBLIC_APP_ENV`) is not `production`, decided at\n * runtime so one image serves every stage; without an app env only in dev mode (a production build fails closed).\n * `enabled` (or `NG_PUBLIC_LT_BUG_ENABLED`) overrides the decision.\n *\n * This provider carries only the options: nothing of the reporter is in the initial bundle. `<lt-bug-report>` (from\n * `@lenne.tech/ng-base/bug`) starts the capture when it is created, so render it deferred and only while\n * {@link LT_BUG_ACTIVE} is `true`: production then never loads the reporter, the other stages start capturing right\n * after the first render (`on immediate`).\n *\n * @example app.config.ts\n * import { provideLtBug } from '@lenne.tech/ng-base/bug/provide';\n * providers: [provideLtNgBase(), provideLtUi(), provideLtBug({ autoOpenOnError: true })]\n *\n * @example app.ts / app.html\n * protected readonly bugActive = inject(LT_BUG_ACTIVE);\n * @if (bugActive) { @defer (on immediate) { <lt-bug-report /> } }\n */\nexport function provideLtBug(options: LtBugOptions = {}): EnvironmentProviders {\n return makeEnvironmentProviders([{ provide: LT_BUG_INPUT_OPTIONS, useValue: options }]);\n}\n"],"mappings":";;AAMA,MAAa,uBAAuB,IAAI,eAAoC,wBAAwB,EAAE,eAAe,KAAI,CAAE;AAG3H,MAAa,kBAAkB,IAAI,eAAwB,mBAAmB,EAAE,eAAe,UAAS,EAAE,CAAE;AAU5G,MAAa,gBAAgB,IAAI,eAAwB,iBAAiB,EACxE,eAAc;CACZ,MAAM,UAAU,OAAO,oBAAoB;CAC3C,IAAI,YAAY,MACd,OAAO;CAIT,MAAM,UAAU,OAAO,mBAAmB,EAAE,UAAU,KAAI,CAAE;CAC5D,MAAM,iBAAkB,SAAS,KAAK,MAA4C,EAAE;CAEpF,OAAO,cAAc,EAAE,SADP,OAAO,mBAAmB,YAAY,iBAAiB,QAAQ,QACjD,GAAI,SAAS,QAAQ,OAAO,eAAe,CAAC;AAC5E,EACD,CAAA;AASD,SAAgB,cAAc,SAAwC,QAAiB,SAAgB;CACrG,IAAI,OAAO,QAAQ,YAAY,WAC7B,OAAO,QAAQ;CAEjB,MAAM,MAAM,OAAO,WAAW,WAAW,OAAO,KAAI,CAAE,CAAC,YAAW,IAAK;CACvE,IAAI,CAAC,KACH,OAAO;CAET,OAAO,QAAQ,gBAAgB,QAAQ;AACzC;ACvBA,SAAgB,aAAa,UAAwB,CAAA,GAAE;CACrD,OAAO,yBAAyB,CAAC;EAAE,SAAS;EAAsB,UAAU;CAAO,CAAE,CAAC;AACxF"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
function emptyLtBugReportForm() {
|
|
2
|
+
return {
|
|
3
|
+
description: "",
|
|
4
|
+
expectedBehavior: "",
|
|
5
|
+
stepsToReproduce: "",
|
|
6
|
+
title: "",
|
|
7
|
+
type: null
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function buildLtBugReport(form, attachments, includes, sources) {
|
|
11
|
+
const data = {
|
|
12
|
+
description: form.description.trim(),
|
|
13
|
+
title: form.title.trim(),
|
|
14
|
+
type: form.type ?? "bug"
|
|
15
|
+
};
|
|
16
|
+
const expected = form.expectedBehavior.trim();
|
|
17
|
+
const steps = form.stepsToReproduce.trim();
|
|
18
|
+
if (expected) data.expectedBehavior = expected;
|
|
19
|
+
if (steps) data.stepsToReproduce = steps;
|
|
20
|
+
if (attachments.length) data.attachments = attachments.map(({ data: content, id, isScreenshot, name, size, type }) => ({
|
|
21
|
+
data: content,
|
|
22
|
+
id,
|
|
23
|
+
name,
|
|
24
|
+
size,
|
|
25
|
+
type,
|
|
26
|
+
...isScreenshot ? { isScreenshot } : {}
|
|
27
|
+
}));
|
|
28
|
+
if (includes.browserInfo && sources.browserInfo) try {
|
|
29
|
+
data.browserInfo = sources.browserInfo();
|
|
30
|
+
} catch {}
|
|
31
|
+
if (includes.consoleLogs && sources.consoleLogs) data.consoleLogs = sources.consoleLogs();
|
|
32
|
+
if (includes.networkRequests && sources.networkRequests) data.networkRequests = sources.networkRequests();
|
|
33
|
+
if (includes.userJourney && sources.userInteractions) data.userInteractions = sources.userInteractions();
|
|
34
|
+
return data;
|
|
35
|
+
}
|
|
36
|
+
function ltBugPrefillFromError(error) {
|
|
37
|
+
return {
|
|
38
|
+
description: `**Error Message:**\n${error.message}\n\n**Component:** ${error.componentName || "Unknown"}\n\n**Stack Trace:**\n\`\`\`\n${error.stack || "No stack trace available"}\n\`\`\``,
|
|
39
|
+
title: error.message.slice(0, 100),
|
|
40
|
+
type: "bug"
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function ltDataUrlSize(dataUrl) {
|
|
44
|
+
const comma = dataUrl.indexOf(",");
|
|
45
|
+
const base64 = comma >= 0 ? dataUrl.slice(comma + 1) : dataUrl;
|
|
46
|
+
const padding = base64.endsWith("==") ? 2 : base64.endsWith("=") ? 1 : 0;
|
|
47
|
+
return Math.max(0, Math.floor(base64.length * 3 / 4) - padding);
|
|
48
|
+
}
|
|
49
|
+
function formatLtBugFileSize(bytes) {
|
|
50
|
+
if (!bytes) return "0 Bytes";
|
|
51
|
+
const units = [
|
|
52
|
+
"Bytes",
|
|
53
|
+
"KB",
|
|
54
|
+
"MB",
|
|
55
|
+
"GB"
|
|
56
|
+
];
|
|
57
|
+
const index = Math.min(units.length - 1, Math.floor(Math.log(bytes) / Math.log(1024)));
|
|
58
|
+
return `${Math.round(bytes / 1024 ** index * 100) / 100} ${units[index]}`;
|
|
59
|
+
}
|
|
60
|
+
export { buildLtBugReport, emptyLtBugReportForm, formatLtBugFileSize, ltBugPrefillFromError, ltDataUrlSize };
|
|
61
|
+
|
|
62
|
+
//# sourceMappingURL=lenne.tech-ng-base-bug-report-Tzlhe1Cm.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lenne.tech-ng-base-bug-report-Tzlhe1Cm.mjs","names":[],"sources":["../../../projects/ng-base/bug/src/lib/report.ts"],"sourcesContent":["import type {\n LtBrowserInfo,\n LtBugAttachment,\n LtBugErrorInfo,\n LtBugReportData,\n LtBugReportType,\n LtConsoleLogEntry,\n LtNetworkRequestEntry,\n LtUserInteractionEvent,\n} from './bug-types';\n\n/** Values of the report form. */\nexport interface LtBugReportFormValue {\n description: string;\n expectedBehavior: string;\n stepsToReproduce: string;\n title: string;\n type: LtBugReportType | null;\n}\n\n/** Which collected data the user chose to include. */\nexport interface LtBugReportIncludes {\n browserInfo: boolean;\n consoleLogs: boolean;\n networkRequests: boolean;\n userJourney: boolean;\n}\n\n/** Collected data; a missing source means the feature is disabled. */\nexport interface LtBugReportSources {\n browserInfo?: () => LtBrowserInfo;\n consoleLogs?: () => LtConsoleLogEntry[];\n networkRequests?: () => LtNetworkRequestEntry[];\n userInteractions?: () => LtUserInteractionEvent[];\n}\n\n/** An empty form. */\nexport function emptyLtBugReportForm(): LtBugReportFormValue {\n return { description: '', expectedBehavior: '', stepsToReproduce: '', title: '', type: null };\n}\n\n/**\n * Assemble the payload for the server endpoint: trimmed form values, attachments without their preview copy, and the\n * collected data the user kept switched on (only for enabled features, i.e. when a source exists).\n */\nexport function buildLtBugReport(form: LtBugReportFormValue, attachments: readonly LtBugAttachment[], includes: LtBugReportIncludes, sources: LtBugReportSources): LtBugReportData {\n const data: LtBugReportData = {\n description: form.description.trim(),\n title: form.title.trim(),\n type: form.type ?? 'bug',\n };\n const expected = form.expectedBehavior.trim();\n const steps = form.stepsToReproduce.trim();\n if (expected) {\n data.expectedBehavior = expected;\n }\n if (steps) {\n data.stepsToReproduce = steps;\n }\n if (attachments.length) {\n data.attachments = attachments.map(({ data: content, id, isScreenshot, name, size, type }) => ({\n data: content,\n id,\n name,\n size,\n type,\n ...(isScreenshot ? { isScreenshot } : {}),\n }));\n }\n if (includes.browserInfo && sources.browserInfo) {\n try {\n data.browserInfo = sources.browserInfo();\n } catch {\n // Not available (e.g. no navigator): send the report without it.\n }\n }\n if (includes.consoleLogs && sources.consoleLogs) {\n data.consoleLogs = sources.consoleLogs();\n }\n if (includes.networkRequests && sources.networkRequests) {\n data.networkRequests = sources.networkRequests();\n }\n if (includes.userJourney && sources.userInteractions) {\n data.userInteractions = sources.userInteractions();\n }\n return data;\n}\n\n/** Form pre-fill for a captured error (same text as `@lenne.tech/bug.lt`). */\nexport function ltBugPrefillFromError(error: LtBugErrorInfo): Pick<LtBugReportFormValue, 'description' | 'title' | 'type'> {\n return {\n description: `**Error Message:**\\n${error.message}\\n\\n**Component:** ${error.componentName || 'Unknown'}\\n\\n**Stack Trace:**\\n\\`\\`\\`\\n${error.stack || 'No stack trace available'}\\n\\`\\`\\``,\n title: error.message.slice(0, 100),\n type: 'bug',\n };\n}\n\n/** Decoded size in bytes of a base64 data URL. */\nexport function ltDataUrlSize(dataUrl: string): number {\n const comma = dataUrl.indexOf(',');\n const base64 = comma >= 0 ? dataUrl.slice(comma + 1) : dataUrl;\n const padding = base64.endsWith('==') ? 2 : base64.endsWith('=') ? 1 : 0;\n return Math.max(0, Math.floor((base64.length * 3) / 4) - padding);\n}\n\n/** Human readable file size (`0 Bytes`, `1.5 KB`, `2 MB`). */\nexport function formatLtBugFileSize(bytes: number): string {\n if (!bytes) {\n return '0 Bytes';\n }\n const units = ['Bytes', 'KB', 'MB', 'GB'];\n const index = Math.min(units.length - 1, Math.floor(Math.log(bytes) / Math.log(1024)));\n return `${Math.round((bytes / 1024 ** index) * 100) / 100} ${units[index]}`;\n}\n"],"mappings":"AAqCA,SAAgB,uBAAoB;CAClC,OAAO;EAAE,aAAa;EAAI,kBAAkB;EAAI,kBAAkB;EAAI,OAAO;EAAI,MAAM;CAAI;AAC7F;AAMA,SAAgB,iBAAiB,MAA4B,aAAyC,UAA+B,SAA2B;CAC9J,MAAM,OAAwB;EAC5B,aAAa,KAAK,YAAY,KAAI;EAClC,OAAO,KAAK,MAAM,KAAI;EACtB,MAAM,KAAK,QAAQ;CACpB;CACD,MAAM,WAAW,KAAK,iBAAiB,KAAI;CAC3C,MAAM,QAAQ,KAAK,iBAAiB,KAAI;CACxC,IAAI,UACF,KAAK,mBAAmB;CAE1B,IAAI,OACF,KAAK,mBAAmB;CAE1B,IAAI,YAAY,QACd,KAAK,cAAc,YAAY,KAAK,EAAE,MAAM,SAAS,IAAI,cAAc,MAAM,MAAM,YAAY;EAC7F,MAAM;EACN;EACA;EACA;EACA;EACA,GAAI,eAAe,EAAE,aAAY,IAAK,CAAA;CACvC,EAAC;CAEJ,IAAI,SAAS,eAAe,QAAQ,aAClC,IAAI;EACF,KAAK,cAAc,QAAQ,YAAW;CACxC,QAAQ,CAER;CAEF,IAAI,SAAS,eAAe,QAAQ,aAClC,KAAK,cAAc,QAAQ,YAAW;CAExC,IAAI,SAAS,mBAAmB,QAAQ,iBACtC,KAAK,kBAAkB,QAAQ,gBAAe;CAEhD,IAAI,SAAS,eAAe,QAAQ,kBAClC,KAAK,mBAAmB,QAAQ,iBAAgB;CAElD,OAAO;AACT;AAGA,SAAgB,sBAAsB,OAAqB;CACzD,OAAO;EACL,aAAa,uBAAuB,MAAM,QAAO,qBAAsB,MAAM,iBAAiB,UAAS,gCAAiC,MAAM,SAAS,2BAA0B;EACjL,OAAO,MAAM,QAAQ,MAAM,GAAG,GAAG;EACjC,MAAM;CACP;AACH;AAGA,SAAgB,cAAc,SAAe;CAC3C,MAAM,QAAQ,QAAQ,QAAQ,GAAG;CACjC,MAAM,SAAS,SAAS,IAAI,QAAQ,MAAM,QAAQ,CAAC,IAAI;CACvD,MAAM,UAAU,OAAO,SAAS,IAAI,IAAI,IAAI,OAAO,SAAS,GAAG,IAAI,IAAI;CACvE,OAAO,KAAK,IAAI,GAAG,KAAK,MAAO,OAAO,SAAS,IAAK,CAAC,IAAI,OAAO;AAClE;AAGA,SAAgB,oBAAoB,OAAa;CAC/C,IAAI,CAAC,OACH,OAAO;CAET,MAAM,QAAQ;EAAC;EAAS;EAAM;EAAM;CAAI;CACxC,MAAM,QAAQ,KAAK,IAAI,MAAM,SAAS,GAAG,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC;CACrF,OAAO,GAAG,KAAK,MAAO,QAAQ,QAAQ,QAAS,GAAG,IAAI,IAAG,GAAI,MAAM;AACrE"}
|