@backtrack-js/browser 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/capturers/console.d.ts +0 -1
- package/dist/capturers/errors.d.ts +0 -1
- package/dist/capturers/index.d.ts +0 -1
- package/dist/capturers/navigation.d.ts +0 -1
- package/dist/capturers/network.d.ts +0 -1
- package/dist/capturers/performance.d.ts +0 -1
- package/dist/capturers/route-matcher.d.ts +0 -1
- package/dist/capturers/rrweb.d.ts +0 -1
- package/dist/capturers/sanitizer.d.ts +0 -1
- package/dist/core/flight-recorder.d.ts +0 -1
- package/dist/core/state-machine.d.ts +0 -1
- package/dist/dev-server/index.d.ts +0 -1
- package/dist/dev-server/middleware.d.ts +0 -1
- package/dist/dev-server.cjs +0 -1
- package/dist/dev-server.js +0 -1
- package/dist/index.cjs +1 -2
- package/dist/index.d.ts +0 -1
- package/dist/index.js +1 -2
- package/dist/markdown-Ao5Ah9MF.cjs +0 -1
- package/dist/markdown-D3C94OlY.js +0 -1
- package/dist/storage/batch-writer.d.ts +0 -1
- package/dist/storage/db.d.ts +0 -1
- package/dist/storage/incident-manager.d.ts +0 -1
- package/dist/storage/index.d.ts +0 -1
- package/dist/storage/retention.d.ts +0 -1
- package/dist/storage/session.d.ts +0 -1
- package/dist/types/artifact.d.ts +0 -1
- package/dist/types/chunk.d.ts +0 -1
- package/dist/types/health.d.ts +0 -1
- package/dist/types/incident.d.ts +0 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/options.d.ts +0 -1
- package/dist/types/timeline.d.ts +0 -1
- package/dist/types/transport.d.ts +0 -1
- package/dist/utils/compression.d.ts +0 -1
- package/dist/utils/gist-uploader.d.ts +0 -1
- package/dist/utils/markdown.d.ts +0 -1
- package/dist/validation/validate.d.ts +0 -1
- package/dist/viewer/assets/{index-D8m3bwRf.js → index-BkV3C4kX.js} +1 -1
- package/dist/viewer/index.html +1 -1
- package/dist/widget/annotator.d.ts +0 -1
- package/dist/widget/styles.d.ts +0 -1
- package/dist/widget/widget.d.ts +0 -1
- package/package.json +13 -4
- package/dist/capturers/console.d.ts.map +0 -1
- package/dist/capturers/errors.d.ts.map +0 -1
- package/dist/capturers/index.d.ts.map +0 -1
- package/dist/capturers/navigation.d.ts.map +0 -1
- package/dist/capturers/network.d.ts.map +0 -1
- package/dist/capturers/performance.d.ts.map +0 -1
- package/dist/capturers/route-matcher.d.ts.map +0 -1
- package/dist/capturers/rrweb.d.ts.map +0 -1
- package/dist/capturers/sanitizer.d.ts.map +0 -1
- package/dist/core/flight-recorder.d.ts.map +0 -1
- package/dist/core/state-machine.d.ts.map +0 -1
- package/dist/dev-server/index.d.ts.map +0 -1
- package/dist/dev-server/middleware.d.ts.map +0 -1
- package/dist/dev-server.cjs.map +0 -1
- package/dist/dev-server.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/markdown-Ao5Ah9MF.cjs.map +0 -1
- package/dist/markdown-D3C94OlY.js.map +0 -1
- package/dist/storage/batch-writer.d.ts.map +0 -1
- package/dist/storage/db.d.ts.map +0 -1
- package/dist/storage/incident-manager.d.ts.map +0 -1
- package/dist/storage/index.d.ts.map +0 -1
- package/dist/storage/retention.d.ts.map +0 -1
- package/dist/storage/session.d.ts.map +0 -1
- package/dist/types/artifact.d.ts.map +0 -1
- package/dist/types/chunk.d.ts.map +0 -1
- package/dist/types/health.d.ts.map +0 -1
- package/dist/types/incident.d.ts.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/options.d.ts.map +0 -1
- package/dist/types/timeline.d.ts.map +0 -1
- package/dist/types/transport.d.ts.map +0 -1
- package/dist/utils/compression.d.ts.map +0 -1
- package/dist/utils/gist-uploader.d.ts.map +0 -1
- package/dist/utils/markdown.d.ts.map +0 -1
- package/dist/validation/validate.d.ts.map +0 -1
- package/dist/widget/annotator.d.ts.map +0 -1
- package/dist/widget/styles.d.ts.map +0 -1
- package/dist/widget/widget.d.ts.map +0 -1
package/dist/widget/styles.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
1
|
export declare const WIDGET_CSS = "\n/* ==========================================================================\n Backtrack Trigger Widget \u2014 Dark Theme Design System (Shadow DOM)\n ========================================================================== */\n\n:host, .backtrack-root {\n --bt-surface-bg: #0f1117;\n --bt-surface-card: #161a23;\n --bt-surface-elevated: #1e2430;\n --bt-surface-input: #131720;\n --bt-border: #262d3d;\n --bt-border-subtle: #1c212c;\n --bt-text-primary: #f8fafc;\n --bt-text-muted: #94a3b8;\n --bt-text-dim: #64748b;\n --bt-accent: #2563eb;\n --bt-accent-hover: #1d4ed8;\n --bt-accent-muted: rgba(37, 99, 235, 0.16);\n --bt-status-online: #22c55e;\n --bt-bg-success: rgba(34, 197, 94, 0.12);\n --bt-text-success: #22c55e;\n --bt-border-success: rgba(34, 197, 94, 0.4);\n --bt-bg-danger: rgba(239, 68, 68, 0.12);\n --bt-text-danger: #ef4444;\n --bt-border-danger: rgba(239, 68, 68, 0.4);\n --bt-radius-lg: 12px;\n --bt-radius-md: 8px;\n --bt-radius-sm: 6px;\n --bt-font: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;\n --bt-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n\n all: initial;\n position: fixed;\n bottom: max(16px, env(safe-area-inset-bottom, 16px));\n left: max(16px, env(safe-area-inset-left, 16px));\n z-index: 999999;\n font-family: var(--bt-font);\n color: var(--bt-text-primary);\n box-sizing: border-box;\n}\n\n*, *::before, *::after {\n box-sizing: border-box;\n}\n\n.backtrack-root {\n position: relative;\n}\n\n/* Launcher Flutuante */\n.backtrack-launcher-btn {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 38px;\n height: 38px;\n padding: 0;\n background-color: var(--bt-surface-bg);\n color: var(--bt-text-primary);\n border: 1px solid var(--bt-border);\n border-radius: var(--bt-radius-sm);\n cursor: pointer;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);\n transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;\n user-select: none;\n touch-action: manipulation;\n outline: none;\n}\n\n.backtrack-launcher-btn:hover {\n background-color: var(--bt-surface-elevated);\n border-color: var(--bt-accent);\n color: var(--bt-accent);\n}\n\n.backtrack-launcher-btn:focus-visible {\n outline: 2px solid var(--bt-accent);\n outline-offset: 1px;\n}\n\n.backtrack-launcher-btn:active {\n transform: translateY(1px);\n}\n\n.backtrack-launcher-status-dot {\n position: absolute;\n bottom: 3px;\n right: 3px;\n width: 7px;\n height: 7px;\n border-radius: 50%;\n border: 1px solid var(--bt-surface-bg);\n display: inline-block;\n pointer-events: none;\n}\n\n.backtrack-status-recording {\n background-color: #22c55e;\n box-shadow: 0 0 5px #22c55e;\n}\n\n.backtrack-status-degraded {\n background-color: #f59e0b;\n box-shadow: 0 0 4px #f59e0b;\n}\n\n.backtrack-status-idle {\n background-color: #64748b;\n}\n\n.backtrack-incident-badge-count {\n position: absolute;\n top: -4px;\n right: -4px;\n background-color: #ef4444;\n color: #ffffff;\n border: 1px solid var(--bt-surface-bg);\n border-radius: 4px;\n padding: 0 4px;\n font-family: var(--bt-font-mono);\n font-size: 9px;\n font-weight: 700;\n line-height: 13px;\n pointer-events: none;\n}\n\n/* Painel Modal / Drawer */\n.backtrack-panel {\n position: fixed;\n bottom: 60px;\n left: 16px;\n width: 340px;\n max-height: 540px;\n background-color: var(--bt-surface-bg);\n border: 1px solid var(--bt-border);\n border-radius: var(--bt-radius-lg);\n box-shadow: 0 14px 36px rgba(0, 0, 0, 0.65);\n z-index: 999999;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n font-family: var(--bt-font);\n animation: backtrackFadeIn 0.15s ease-out;\n}\n\n@keyframes backtrackFadeIn {\n from { opacity: 0; transform: translateY(6px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n/* 1. Cabe\u00E7alho do Painel */\n.backtrack-panel-header {\n background-color: transparent;\n border-bottom: 1px solid var(--bt-border);\n padding: 12px 14px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.backtrack-header-left {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.backtrack-header-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--bt-text-primary);\n letter-spacing: -0.01em;\n}\n\n.backtrack-header-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background-color: var(--bt-status-online);\n flex-shrink: 0;\n}\n\n.backtrack-header-right {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.backtrack-header-icon-btn {\n background: transparent;\n border: none;\n color: var(--bt-text-muted);\n width: 20px;\n height: 20px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n padding: 0;\n transition: color 0.12s ease;\n outline: none;\n}\n\n.backtrack-header-icon-btn:hover {\n color: var(--bt-text-primary);\n}\n\n.backtrack-storage-tooltip-trigger {\n color: var(--bt-text-muted);\n cursor: help;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n transition: color 0.12s ease;\n}\n\n.backtrack-storage-tooltip-trigger:hover {\n color: var(--bt-text-primary);\n}\n\n/* Menu de 3 Pontos do Cabe\u00E7alho */\n.backtrack-header-menu-wrap {\n position: relative;\n display: inline-flex;\n}\n\n.backtrack-header-menu {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n background-color: var(--bt-surface-card);\n border: 1px solid var(--bt-border);\n border-radius: var(--bt-radius-md);\n box-shadow: 0 10px 25px rgba(0, 0, 0, 0.6);\n min-width: 190px;\n z-index: 1000;\n padding: 5px;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.backtrack-header-menu-info {\n padding: 8px 10px 6px 10px;\n font-size: 11px;\n color: var(--bt-text-muted);\n font-family: var(--bt-font-mono);\n border-bottom: 1px solid var(--bt-border);\n margin-bottom: 4px;\n}\n\n.backtrack-header-menu-item {\n background: transparent;\n border: none;\n border-radius: var(--bt-radius-sm);\n padding: 8px 10px;\n color: var(--bt-text-primary);\n font-size: 12px;\n text-align: left;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 8px;\n transition: background-color 0.1s ease, color 0.1s ease;\n width: 100%;\n}\n\n.backtrack-header-menu-item:hover {\n background-color: var(--bt-surface-elevated);\n color: #ffffff;\n}\n\n/* Corpo do Painel */\n.backtrack-panel-body {\n padding: 12px 14px;\n overflow-y: auto;\n flex: 1;\n scrollbar-width: thin;\n scrollbar-color: #334155 transparent;\n}\n\n.backtrack-panel-body::-webkit-scrollbar {\n width: 5px;\n}\n\n.backtrack-panel-body::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.backtrack-panel-body::-webkit-scrollbar-thumb {\n background-color: #334155;\n border-radius: 4px;\n}\n\n.backtrack-panel-body::-webkit-scrollbar-thumb:hover {\n background-color: #475569;\n}\n\n/* Banner Inline (Sucesso / Falha) */\n.backtrack-banner {\n display: flex;\n align-items: center;\n gap: 8px;\n border-radius: var(--bt-radius-md);\n padding: 10px 12px;\n margin-bottom: 12px;\n font-size: 13px;\n line-height: 1.4;\n animation: backtrackFadeIn 0.15s ease-out;\n}\n\n.backtrack-banner-success {\n background-color: var(--bt-bg-success);\n color: var(--bt-text-success);\n}\n\n.backtrack-banner-danger {\n background-color: var(--bt-bg-danger);\n color: var(--bt-text-danger);\n}\n\n.backtrack-banner-icon {\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.backtrack-banner-success .backtrack-banner-icon {\n color: var(--bt-text-success);\n}\n\n.backtrack-banner-danger .backtrack-banner-icon {\n color: var(--bt-text-danger);\n}\n\n.backtrack-banner-text {\n flex: 1;\n font-weight: 500;\n font-size: 13px;\n}\n\n.backtrack-banner-close {\n background: transparent;\n border: none;\n padding: 2px 4px;\n cursor: pointer;\n opacity: 0.7;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n transition: opacity 0.12s ease;\n outline: none;\n}\n\n.backtrack-banner-success .backtrack-banner-close {\n color: var(--bt-text-success);\n}\n\n.backtrack-banner-danger .backtrack-banner-close {\n color: var(--bt-text-danger);\n}\n\n.backtrack-banner-close:hover {\n opacity: 1;\n}\n\n/* Toast Flutuante (Sobreposto e Tempor\u00E1rio) */\n.backtrack-toast-wrap {\n position: absolute;\n bottom: 14px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 1000;\n pointer-events: none;\n width: max-content;\n max-width: calc(100% - 28px);\n animation: backtrackToastIn 0.2s cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n@keyframes backtrackToastIn {\n from {\n opacity: 0;\n transform: translate(-50%, 6px);\n }\n to {\n opacity: 1;\n transform: translate(-50%, 0);\n }\n}\n\n.backtrack-toast {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n background-color: var(--bt-surface-bg);\n border-radius: var(--bt-radius-md);\n padding: 8px 14px;\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.65);\n pointer-events: auto;\n}\n\n.backtrack-toast-success {\n border: 1px solid var(--bt-border-success);\n}\n\n.backtrack-toast-danger {\n border: 1px solid var(--bt-border-danger);\n}\n\n.backtrack-toast-icon {\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.backtrack-toast-success .backtrack-toast-icon {\n color: var(--bt-text-success);\n}\n\n.backtrack-toast-danger .backtrack-toast-icon {\n color: var(--bt-text-danger);\n}\n\n.backtrack-toast-text {\n color: var(--bt-text-primary);\n font-size: 13px;\n font-weight: 500;\n white-space: nowrap;\n}\n\n/* 2. Se\u00E7\u00E3o de Controles de Grava\u00E7\u00E3o */\n.backtrack-controls-section {\n margin-bottom: 16px;\n}\n\n.backtrack-section-label-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 8px;\n}\n\n.backtrack-section-label {\n font-size: 12px;\n font-weight: 500;\n color: var(--bt-text-muted);\n}\n\n.backtrack-help-tooltip-trigger {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n color: var(--bt-text-muted);\n cursor: help;\n font-size: 11px;\n transition: color 0.15s ease;\n}\n\n.backtrack-help-tooltip-trigger:hover {\n color: var(--bt-text-secondary);\n}\n\n.backtrack-duration-grid {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 6px;\n margin-bottom: 10px;\n}\n\n.backtrack-duration-btn {\n background-color: var(--bt-surface-card);\n border: 1px solid var(--bt-border);\n border-radius: var(--bt-radius-md);\n height: 32px;\n font-size: 12px;\n font-weight: 500;\n color: var(--bt-text-primary);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n transition: background-color 0.1s ease, border-color 0.1s ease, color 0.1s ease;\n user-select: none;\n outline: none;\n}\n\n.backtrack-duration-btn:hover {\n background-color: var(--bt-surface-elevated);\n border-color: #3b4252;\n color: #ffffff;\n}\n\n.backtrack-duration-btn.is-selected {\n background-color: var(--bt-accent-muted);\n border-color: var(--bt-accent);\n color: #60a5fa;\n font-weight: 600;\n}\n\n.backtrack-custom-duration-row {\n background-color: var(--bt-surface-card);\n border: 1px solid var(--bt-border);\n border-radius: var(--bt-radius-sm);\n padding: 6px 10px;\n margin-bottom: 10px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n\n.backtrack-custom-input-wrap {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.backtrack-custom-duration-input {\n background-color: var(--bt-surface-input);\n border: 1px solid var(--bt-accent);\n border-radius: var(--bt-radius-sm);\n color: var(--bt-text-primary);\n font-family: var(--bt-font-mono);\n font-size: 12px;\n font-weight: 600;\n width: 65px;\n padding: 3px 6px;\n outline: none;\n text-align: right;\n}\n\n.backtrack-custom-duration-input:focus {\n border-color: #60a5fa;\n box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.3);\n}\n\n.backtrack-custom-unit {\n font-size: 11px;\n color: var(--bt-text-muted);\n}\n\n.backtrack-custom-hint {\n font-size: 10.5px;\n color: var(--bt-text-dim);\n white-space: nowrap;\n}\n\n/* Linha de A\u00E7\u00F5es */\n.backtrack-actions-row {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.backtrack-btn-save {\n flex: 1;\n height: 36px;\n background-color: var(--bt-accent);\n color: #ffffff;\n border: 1px solid #3b82f6;\n border-radius: var(--bt-radius-md);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n transition: background-color 0.12s ease;\n user-select: none;\n outline: none;\n}\n\n.backtrack-btn-save:hover:not(:disabled) {\n background-color: var(--bt-accent-hover);\n}\n\n.backtrack-btn-save:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.backtrack-btn-icon-square {\n width: 36px;\n height: 36px;\n border-radius: var(--bt-radius-md);\n border: 1px solid var(--bt-border);\n background-color: var(--bt-surface-card);\n color: var(--bt-text-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n flex-shrink: 0;\n transition: background-color 0.1s ease, border-color 0.1s ease, color 0.1s ease;\n outline: none;\n padding: 0;\n}\n\n.backtrack-btn-icon-square:hover:not(:disabled) {\n background-color: var(--bt-surface-elevated);\n border-color: #3b4252;\n color: #ffffff;\n}\n\n.backtrack-btn-icon-square:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* 3. Se\u00E7\u00E3o de Lista de Grava\u00E7\u00F5es Salvas */\n.backtrack-list-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.backtrack-list-title {\n font-size: 12px;\n font-weight: 500;\n color: var(--bt-text-muted);\n}\n\n.backtrack-list-count {\n font-size: 12px;\n font-weight: 500;\n color: var(--bt-text-muted);\n}\n\n.backtrack-list-item {\n background-color: var(--bt-surface-card);\n border: 1px solid var(--bt-border);\n border-radius: var(--bt-radius-md);\n padding: 9px 12px;\n margin-bottom: 6px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n cursor: pointer;\n transition: background-color 0.12s ease, border-color 0.12s ease;\n text-align: left;\n width: 100%;\n box-sizing: border-box;\n}\n\n.backtrack-list-item:hover {\n background-color: var(--bt-surface-elevated);\n border-color: #3b4252;\n}\n\n.backtrack-item-content {\n display: flex;\n flex-direction: column;\n gap: 2px;\n overflow: hidden;\n}\n\n.backtrack-item-title {\n font-size: 13px;\n font-weight: 500;\n color: var(--bt-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.backtrack-item-meta {\n font-size: 12px;\n color: var(--bt-text-muted);\n}\n\n.backtrack-item-chevron {\n color: var(--bt-text-muted);\n flex-shrink: 0;\n margin-left: 8px;\n display: flex;\n align-items: center;\n}\n\n/* Estado Vazio */\n.backtrack-empty-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 24px 16px;\n background-color: var(--bt-surface-card);\n border: 1px dashed var(--bt-border);\n border-radius: var(--bt-radius-md);\n text-align: center;\n}\n\n.backtrack-empty-title {\n font-size: 13px;\n font-weight: 500;\n color: var(--bt-text-primary);\n margin-top: 8px;\n margin-bottom: 2px;\n}\n\n.backtrack-empty-desc {\n font-size: 12px;\n color: var(--bt-text-muted);\n line-height: 1.4;\n}\n\n/* 4. Tela de Detalhe do Incidente */\n.backtrack-detail-view {\n display: flex;\n flex-direction: column;\n}\n\n.backtrack-detail-back-row {\n margin-bottom: 14px;\n}\n\n.backtrack-btn-back {\n background: transparent;\n border: 1px solid var(--bt-border);\n border-radius: var(--bt-radius-sm);\n padding: 5px 10px;\n font-size: 13px;\n font-weight: 400;\n color: var(--bt-text-primary);\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n transition: background-color 0.12s ease, border-color 0.12s ease;\n outline: none;\n}\n\n.backtrack-btn-back:hover {\n background-color: var(--bt-surface-elevated);\n border-color: #3b4252;\n}\n\n.backtrack-detail-card {\n background-color: var(--bt-surface-card);\n border: 1px solid var(--bt-border);\n border-radius: var(--bt-radius-md);\n padding: 10px 12px;\n margin-bottom: 18px;\n}\n\n.backtrack-detail-title {\n font-size: 14px;\n font-weight: 500;\n color: var(--bt-text-primary);\n margin-bottom: 4px;\n line-height: 1.3;\n}\n\n.backtrack-detail-meta {\n font-size: 12px;\n color: var(--bt-text-muted);\n font-family: var(--bt-font-mono);\n letter-spacing: -0.01em;\n}\n\n/* CTA principal \u2014 Visualizar replay */\n.backtrack-btn-cta-replay {\n width: 100%;\n height: 40px;\n background-color: var(--bt-accent);\n color: #ffffff;\n border: 1px solid #3b82f6;\n border-radius: var(--bt-radius-md);\n font-size: 13px;\n font-weight: 500;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n cursor: pointer;\n transition: background-color 0.12s ease;\n user-select: none;\n outline: none;\n margin-bottom: 18px;\n}\n\n.backtrack-btn-cta-replay:hover {\n background-color: var(--bt-accent-hover);\n}\n\n/* Grupo \"Exportar\" (a\u00E7\u00F5es agrupadas) */\n.backtrack-export-section {\n margin-bottom: 18px;\n}\n\n.backtrack-export-label {\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--bt-text-muted);\n margin-bottom: 8px;\n}\n\n.backtrack-export-group {\n border: 1px solid var(--bt-border);\n border-radius: var(--bt-radius-md);\n overflow: hidden;\n background-color: transparent;\n}\n\n.backtrack-export-item {\n width: 100%;\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n background: transparent;\n border: none;\n border-bottom: 1px solid var(--bt-border);\n color: var(--bt-text-primary);\n font-size: 13px;\n text-align: left;\n cursor: pointer;\n transition: background-color 0.12s ease;\n outline: none;\n}\n\n.backtrack-export-item:last-child {\n border-bottom: none;\n}\n\n.backtrack-export-item svg {\n color: var(--bt-text-muted);\n flex-shrink: 0;\n transition: color 0.12s ease;\n}\n\n.backtrack-export-item:hover {\n background-color: var(--bt-surface-elevated);\n}\n\n.backtrack-export-item:hover svg {\n color: var(--bt-text-primary);\n}\n\n/* A\u00E7\u00E3o destrutiva \u2014 Excluir grava\u00E7\u00E3o */\n.backtrack-destructive-section {\n border-top: 1px solid var(--bt-border);\n padding-top: 12px;\n}\n\n.backtrack-btn-delete-ghost {\n width: 100%;\n background: transparent;\n border: none;\n padding: 6px 0;\n display: flex;\n align-items: center;\n gap: 8px;\n color: #ef4444;\n font-size: 13px;\n font-weight: 400;\n cursor: pointer;\n text-align: left;\n transition: opacity 0.12s ease;\n outline: none;\n}\n\n.backtrack-btn-delete-ghost:hover {\n opacity: 0.8;\n}\n\n.backtrack-btn-delete-ghost svg {\n color: #ef4444;\n flex-shrink: 0;\n}\n\n\n/* Modais de Confirma\u00E7\u00E3o (Export, Download, Hide) */\n.backtrack-modal-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: var(--bt-surface-bg);\n display: flex;\n flex-direction: column;\n z-index: 1000;\n border-radius: var(--bt-radius-lg);\n padding: 0;\n overflow: hidden;\n}\n\n.backtrack-modal-card {\n width: 100%;\n height: 100%;\n max-width: 100%;\n background-color: var(--bt-surface-bg);\n border: none;\n border-radius: var(--bt-radius-lg);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.backtrack-modal-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 14px;\n border-bottom: 1px solid var(--bt-border);\n background-color: var(--bt-surface-bg);\n}\n\n.backtrack-modal-title {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n font-weight: 600;\n color: var(--bt-text-primary);\n}\n\n.backtrack-modal-close {\n background: transparent;\n border: none;\n color: var(--bt-text-muted);\n font-size: 14px;\n cursor: pointer;\n padding: 2px 4px;\n line-height: 1;\n}\n\n.backtrack-modal-close:hover {\n color: #f1f5f9;\n}\n\n.backtrack-modal-body {\n padding: 12px 14px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n flex: 1;\n overflow-y: auto;\n scrollbar-width: thin;\n scrollbar-color: #334155 transparent;\n}\n\n.backtrack-modal-body::-webkit-scrollbar {\n width: 5px;\n}\n\n.backtrack-modal-body::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.backtrack-modal-body::-webkit-scrollbar-thumb {\n background-color: #334155;\n border-radius: 4px;\n}\n\n.backtrack-modal-body::-webkit-scrollbar-thumb:hover {\n background-color: #475569;\n}\n\n.backtrack-modal-checkbox-label {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n cursor: pointer;\n user-select: none;\n}\n\n.backtrack-modal-checkbox-label input[type=\"checkbox\"] {\n margin-top: 2px;\n width: 15px;\n height: 15px;\n accent-color: var(--bt-accent);\n cursor: pointer;\n}\n\n.backtrack-modal-checkbox-title {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: #f1f5f9;\n}\n\n.backtrack-modal-checkbox-desc {\n margin: 3px 0 0 0;\n font-size: 11px;\n color: var(--bt-text-muted);\n line-height: 1.35;\n}\n\n.backtrack-modal-radio-label {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 8px 10px;\n border: 1px solid var(--bt-border);\n border-radius: var(--bt-radius-sm);\n background-color: var(--bt-surface-card);\n cursor: pointer;\n user-select: none;\n transition: border-color 0.1s ease, background-color 0.1s ease;\n}\n\n.backtrack-modal-radio-label:hover {\n background-color: var(--bt-surface-elevated);\n}\n\n.backtrack-modal-radio-label.is-selected {\n border-color: var(--bt-accent);\n background-color: var(--bt-accent-muted);\n}\n\n.backtrack-modal-radio-label input[type=\"radio\"] {\n margin-top: 2px;\n width: 15px;\n height: 15px;\n accent-color: var(--bt-accent);\n cursor: pointer;\n}\n\n.backtrack-modal-radio-title {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: #f1f5f9;\n}\n\n.backtrack-modal-radio-desc {\n margin: 3px 0 0 0;\n font-size: 11px;\n color: var(--bt-text-muted);\n line-height: 1.35;\n}\n\n.backtrack-modal-error {\n padding: 6px 8px;\n background: rgba(239, 68, 68, 0.15);\n border: 1px solid rgba(239, 68, 68, 0.3);\n border-radius: 4px;\n color: #fca5a5;\n font-size: 11px;\n}\n\n.backtrack-modal-footer {\n display: flex;\n justify-content: flex-end;\n gap: 6px;\n padding: 10px 14px;\n border-top: 1px solid var(--bt-border);\n background-color: var(--bt-surface-bg);\n}\n\n.backtrack-btn-secondary {\n background-color: var(--bt-surface-card);\n border: 1px solid var(--bt-border);\n color: #cbd5e1;\n border-radius: var(--bt-radius-sm);\n padding: 5px 10px;\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n}\n\n.backtrack-btn-secondary:hover:not(:disabled) {\n background-color: var(--bt-surface-elevated);\n color: #f8fafc;\n}\n\n.backtrack-btn-primary {\n background-color: var(--bt-accent);\n border: 1px solid #3b82f6;\n color: #ffffff;\n border-radius: var(--bt-radius-sm);\n padding: 5px 12px;\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n}\n\n.backtrack-btn-primary:hover:not(:disabled) {\n background-color: var(--bt-accent-hover);\n}\n\n.backtrack-btn-primary:disabled,\n.backtrack-btn-secondary:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* Responsividade Mobile e Safe Area */\n@media (max-width: 480px) {\n .backtrack-panel {\n width: calc(100vw - 32px);\n max-width: calc(100vw - 16px);\n left: 8px;\n right: 8px;\n bottom: max(60px, env(safe-area-inset-bottom, 60px));\n }\n}\n\n.backtrack-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n}\n";
|
|
2
|
-
//# sourceMappingURL=styles.d.ts.map
|
package/dist/widget/widget.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backtrack-js/browser",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "A flight recorder for your web app. Replay the exact moments before a bug, privately and offline.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -23,9 +23,16 @@
|
|
|
23
23
|
"backtrack": "./bin/cli.js"
|
|
24
24
|
},
|
|
25
25
|
"files": [
|
|
26
|
-
"dist",
|
|
27
|
-
"
|
|
28
|
-
"
|
|
26
|
+
"dist/*.js",
|
|
27
|
+
"dist/*.cjs",
|
|
28
|
+
"dist/**/*.d.ts",
|
|
29
|
+
"dist/viewer/index.html",
|
|
30
|
+
"dist/viewer/assets/*.js",
|
|
31
|
+
"dist/viewer/assets/*.css",
|
|
32
|
+
"dist/viewer/assets/*.png",
|
|
33
|
+
"bin/*.js",
|
|
34
|
+
"bin/*.cjs",
|
|
35
|
+
"dev-server/package.json",
|
|
29
36
|
"README.md",
|
|
30
37
|
"LICENSE"
|
|
31
38
|
],
|
|
@@ -35,6 +42,8 @@
|
|
|
35
42
|
"build:viewer": "vite build viewer --outDir ../dist/viewer --emptyOutDir",
|
|
36
43
|
"build": "npm run build:lib && npm run build:viewer",
|
|
37
44
|
"build:site": "tsx scripts/build-site.ts",
|
|
45
|
+
"check:package": "tsx scripts/verify-package.ts",
|
|
46
|
+
"prepack": "npm run build && npm run check:package",
|
|
38
47
|
"preview:site": "vite preview --outDir dist/site --port 4174 --strictPort",
|
|
39
48
|
"test": "vitest run",
|
|
40
49
|
"test:e2e": "playwright test",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../src/capturers/console.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAG3D,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,gBAAgB,CAAe;IAEvC,OAAO,CAAC,WAAW,CAAmC;IACtD,OAAO,CAAC,YAAY,CAAoC;IACxD,OAAO,CAAC,aAAa,CAAqC;IAE1D,OAAO,CAAC,UAAU,CAAmC;IACrD,OAAO,CAAC,WAAW,CAAoC;IACvD,OAAO,CAAC,YAAY,CAAqC;IAEzD,OAAO,CAAC,YAAY,CAAS;gBAEjB,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,MAAM;IAKxD,KAAK,IAAI,IAAI;IAuBpB,OAAO,CAAC,aAAa;IAkCd,IAAI,IAAI,IAAI;CAsBpB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/capturers/errors.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAEnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,gBAAgB,CAAe;IACvC,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,YAAY,CAAC,CAA8B;IACnD,OAAO,CAAC,gBAAgB,CAAC,CAAyC;gBAGhE,MAAM,EAAE,WAAW,EACnB,eAAe,EAAE,eAAe,EAChC,gBAAgB,EAAE,MAAM,MAAM;IAOzB,KAAK,IAAI,IAAI;IAmBpB,OAAO,CAAC,iBAAiB;IA0BzB,OAAO,CAAC,wBAAwB;IA8BhC;;OAEG;IACI,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,IAAI;IAmCnG,OAAO,CAAC,qBAAqB;IAoDtB,IAAI,IAAI,IAAI;CAepB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/capturers/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../src/capturers/navigation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAG3D,MAAM,WAAW,wBAAwB;IACvC,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,CAAC;CAC5C;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,gBAAgB,CAAe;IACvC,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,iBAAiB,CAAgD;IACzE,OAAO,CAAC,oBAAoB,CAAmD;IAE/E,OAAO,CAAC,eAAe,CAAC,CAAa;IACrC,OAAO,CAAC,iBAAiB,CAAC,CAAa;gBAGrC,MAAM,EAAE,WAAW,EACnB,gBAAgB,EAAE,MAAM,MAAM,EAC9B,MAAM,CAAC,EAAE,wBAAwB;IAO5B,KAAK,IAAI,IAAI;IAyCpB,OAAO,CAAC,gBAAgB;IAoBjB,IAAI,IAAI,IAAI;CAwBpB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../src/capturers/network.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAGnE,MAAM,WAAW,qBAAqB;IACpC,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAClC,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,CAAC;IAC3C,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAUD,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,gBAAgB,CAAe;IACvC,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,YAAY,CAAoC;IAExD,OAAO,CAAC,eAAe,CAAqD;IAC5E,OAAO,CAAC,eAAe,CAAqD;IAC5E,OAAO,CAAC,oBAAoB,CAAiE;IAC7F,OAAO,CAAC,WAAW,CAA8C;gBAG/D,MAAM,EAAE,WAAW,EACnB,eAAe,EAAE,eAAe,EAChC,gBAAgB,EAAE,MAAM,MAAM,EAC9B,MAAM,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC;IAclC,KAAK,IAAI,IAAI;IAQpB,OAAO,CAAC,eAAe;IAkCvB,OAAO,CAAC,eAAe;IAqHvB,OAAO,CAAC,aAAa;IA4HrB,OAAO,CAAC,kBAAkB;IAqDnB,IAAI,IAAI,IAAI;CA6BpB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"performance.d.ts","sourceRoot":"","sources":["../../src/capturers/performance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAG3D,MAAM,WAAW,yBAAyB;IACxC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,gBAAgB,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAoC;IACpD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAS;gBAG1B,MAAM,EAAE,WAAW,EACnB,gBAAgB,EAAE,MAAM,MAAM,EAC9B,MAAM,CAAC,EAAE,yBAAyB;IAO7B,KAAK,IAAI,IAAI;IA0Cb,IAAI,IAAI,IAAI;CAWpB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"route-matcher.d.ts","sourceRoot":"","sources":["../../src/capturers/route-matcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAkBnD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,YAAY,EAAE,GACxB,OAAO,CAsCT"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rrweb.d.ts","sourceRoot":"","sources":["../../src/capturers/rrweb.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAKvD,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,kBAAkB,CAAK;gBAEnB,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,mBAAmB;IAKtD,qBAAqB,IAAI,MAAM;IAI/B,KAAK,IAAI,IAAI;IAkFb,IAAI,IAAI,IAAI;CAapB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sanitizer.d.ts","sourceRoot":"","sources":["../../src/capturers/sanitizer.ts"],"names":[],"mappings":"AA0CA,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,CAAC;CAC5C;AASD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,GAAG,MAAM,CA4BzF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAczD;AAUD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,OAAO,CA8HtF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,GAAE,MAAkB,GAAG,MAAM,CAgB5F;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,SAAS,GAAG,IAAI,GAChF,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAgCpC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"flight-recorder.d.ts","sourceRoot":"","sources":["../../src/core/flight-recorder.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"state-machine.d.ts","sourceRoot":"","sources":["../../src/core/state-machine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAC/B;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,GAC1B;IAAE,IAAI,EAAE,mBAAmB,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,eAAe,CAA0B;IACjD,OAAO,CAAC,wBAAwB,CAA4B;gBAEhD,YAAY,GAAE,aAAyB;IAI5C,QAAQ,IAAI,aAAa;IAIzB,kBAAkB,IAAI,MAAM,EAAE;IAI9B,UAAU,IAAI,OAAO;IAIrB,WAAW,IAAI,OAAO;IAUtB,UAAU,CAAC,KAAK,EAAE,uBAAuB,GAAG,aAAa;CAuDjE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dev-server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EACzB,KAAK,0BAA0B,EAC/B,KAAK,qBAAqB,EAC3B,MAAM,cAAc,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/dev-server/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAM5D,MAAM,WAAW,0BAA0B;IACzC,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AACD,MAAM,MAAM,qBAAqB,GAAG,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,CAAC;AAmCxH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,0BAA0B,GAAG,qBAAqB,CAqKpG"}
|
package/dist/dev-server.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dev-server.cjs","sources":["../src/dev-server/middleware.ts"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from 'http';\nimport fs from 'fs';\nimport path from 'path';\nimport { validateFlightRecorderArtifact } from '../validation/validate';\nimport { formatIncidentMarkdown } from '../utils/markdown';\n\nexport interface BacktrackMiddlewareOptions {\n /** Absolute directory; use only one middleware instance per directory. */\n directory?: string;\n /** Alias for directory. */\n outputDir?: string;\n allowedOrigins?: string[];\n maxBodyBytes?: number;\n maxIncidents?: number;\n maxStorageBytes?: number;\n}\nexport type ConnectLikeMiddleware = (req: IncomingMessage, res: ServerResponse, next?: (err?: unknown) => void) => void;\nconst SAFE_ID = /^[a-zA-Z0-9_-]{1,128}$/;\nconst RESERVED_ID = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])$/i;\nconst safeId = (id: string) => SAFE_ID.test(id) && !RESERVED_ID.test(id);\nconst localHostname = (name: string) => ['localhost', '127.0.0.1', '[::1]'].includes(name.toLowerCase());\nconst localAddress = (address?: string) => address === '127.0.0.1' || address === '::1' || address === '::ffff:127.0.0.1';\nfunction allowedRequest(req: IncomingMessage, origins?: string[]): boolean {\n if (!localAddress(req.socket.remoteAddress)) return false;\n try {\n const host = req.headers.host;\n if (!host) return false;\n const target = new URL(`http://${host}`);\n if (target.host !== host.toLowerCase() || !localHostname(target.hostname)) return false;\n const origin = req.headers.origin;\n if (!origin) return !origins?.length;\n const source = new URL(origin);\n if (!['http:', 'https:'].includes(source.protocol) || !localHostname(source.hostname) || source.origin !== origin) return false;\n return origins?.length ? origins.includes(origin) : source.host === target.host;\n } catch {\n return false;\n }\n}\ninterface ManagedIncident {\n id: string;\n triggeredAt: number;\n jsonPath: string;\n mdPath: string;\n size: number;\n}\nconst compareIncidents = (a: ManagedIncident, b: ManagedIncident) =>\n a.triggeredAt - b.triggeredAt || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0);\nfunction regularFile(file: string): boolean {\n return fs.existsSync(file) && fs.lstatSync(file).isFile();\n}\n\nexport function createBacktrackMiddleware(options: BacktrackMiddlewareOptions): ConnectLikeMiddleware {\n const dir = options?.directory ?? options?.outputDir;\n if (!options || typeof dir !== 'string' || !path.isAbsolute(dir)) {\n throw new Error('[Backtrack dev-server] A opção \"directory\" (ou \"outputDir\") absoluta é obrigatória.');\n }\n const baseDirectory = path.resolve(dir);\n const incidentsDir = path.join(baseDirectory, 'incidents');\n const latestPath = path.join(baseDirectory, 'latest.md');\n const maxBodyBytes = options.maxBodyBytes ?? 50 * 1024 * 1024;\n const maxIncidents = options.maxIncidents ?? 20;\n const maxStorageBytes = options.maxStorageBytes ?? 200 * 1024 * 1024;\n for (const value of [maxBodyBytes, maxIncidents, maxStorageBytes]) {\n if (!Number.isSafeInteger(value) || value <= 0) throw new Error('Backtrack limits must be positive safe integers.');\n }\n if (options.allowedOrigins?.some(origin => {\n try {\n const url = new URL(origin);\n return !localHostname(url.hostname) || !['http:', 'https:'].includes(url.protocol) || url.origin !== origin;\n } catch { return true; }\n })) throw new Error('Backtrack origins must be local HTTP(S) origins.');\n\n // ponytail: synchronous local writes serialized per instance; use async IO if measured dev-server latency warrants it.\n let persistenceQueue = Promise.resolve();\n function scan(): ManagedIncident[] {\n const list: ManagedIncident[] = [];\n for (const file of fs.readdirSync(incidentsDir)) {\n if (!file.endsWith('.json')) continue;\n const id = file.slice(0, -5);\n if (!safeId(id)) continue;\n const jsonPath = path.join(incidentsDir, file);\n const mdPath = path.join(incidentsDir, `${id}.md`);\n try {\n if (!regularFile(jsonPath) || !regularFile(mdPath) || fs.statSync(jsonPath).size > maxBodyBytes) continue;\n const validated = validateFlightRecorderArtifact(JSON.parse(fs.readFileSync(jsonPath, 'utf8')));\n if (!validated.success || validated.data.incident.id !== id) continue;\n if (!fs.readFileSync(mdPath, 'utf8').startsWith('# Incidente Backtrack\\n')) continue;\n list.push({ id, jsonPath, mdPath, triggeredAt: validated.data.incident.triggeredAt, size: fs.statSync(jsonPath).size + fs.statSync(mdPath).size });\n } catch {\n // Unknown, incomplete or invalid files are never retention candidates.\n }\n }\n return list.sort(compareIncidents);\n }\n function publishLatest(): string {\n const list = scan();\n const latest = list[list.length - 1];\n if (!latest) throw new Error('No complete incident to publish');\n const content = `> **Artefato completo:** [\\`${latest.id}.json\\`](incidents/${latest.id}.json)\\n\\n` + fs.readFileSync(latest.mdPath, 'utf8');\n const temporary = `${latestPath}.${Date.now()}.tmp`;\n try {\n fs.writeFileSync(temporary, content, { encoding: 'utf8', flag: 'wx' });\n fs.renameSync(temporary, latestPath);\n } finally {\n if (regularFile(temporary)) fs.unlinkSync(temporary);\n }\n return latest.id;\n }\n function retain(latestId: string): void {\n const list = scan();\n let count = list.length;\n let size = list.reduce((total, item) => total + item.size, fs.statSync(latestPath).size);\n for (const item of list) {\n if (count <= maxIncidents && size <= maxStorageBytes) break;\n if (item.id === latestId) continue;\n fs.unlinkSync(item.mdPath);\n fs.unlinkSync(item.jsonPath);\n count--;\n size -= item.size;\n }\n }\n return (req, res, next) => {\n const respond = (status: number, body: Record<string, unknown>) => {\n if (!res.destroyed && !res.headersSent) {\n res.writeHead(status, { 'Content-Type': 'application/json', ...(status === 405 ? { Allow: 'POST' } : {}) });\n res.end(JSON.stringify(body));\n }\n };\n if ((req.url || '').split('?')[0] !== '/__backtrack/incident') {\n if (next) next(); else respond(404, { error: 'Not found' });\n return;\n }\n if (req.method !== 'POST') { respond(405, { error: 'Method Not Allowed' }); return; }\n if ((req.headers['content-type'] || '').split(';')[0].trim().toLowerCase() !== 'application/json') {\n respond(415, { error: 'Unsupported Media Type: application/json required' }); return;\n }\n if (!allowedRequest(req, options.allowedOrigins)) { respond(403, { error: 'Forbidden: invalid origin or non-local access' }); return; }\n let bytes = 0;\n let rejected = false;\n const chunks: Buffer[] = [];\n req.on('error', () => { rejected = true; chunks.length = 0; });\n req.on('aborted', () => { rejected = true; chunks.length = 0; });\n req.on('data', (chunk: Buffer) => {\n if (rejected) return;\n bytes += chunk.length;\n if (bytes > maxBodyBytes) {\n rejected = true;\n chunks.length = 0;\n res.setHeader('Connection', 'close');\n respond(413, { error: 'Payload Too Large' });\n // Drain without retaining data so the HTTP response can reach the client.\n } else chunks.push(chunk);\n });\n req.on('end', () => {\n if (rejected) return;\n const rawBody = Buffer.concat(chunks).toString('utf8');\n chunks.length = 0;\n let parsed: unknown;\n try { parsed = JSON.parse(rawBody); }\n catch { respond(400, { error: 'Invalid JSON' }); return; }\n const validated = validateFlightRecorderArtifact(parsed);\n if (!validated.success) { respond(400, { error: 'Invalid artifact schema' }); return; }\n const artifact = validated.data;\n const id = artifact.incident.id;\n if (!safeId(id)) { respond(400, { error: 'Invalid incident ID format' }); return; }\n persistenceQueue = persistenceQueue.then(() => {\n try {\n for (const dir of [baseDirectory, incidentsDir]) {\n if (fs.existsSync(dir) && !fs.lstatSync(dir).isDirectory()) throw new Error('Invalid output directory');\n fs.mkdirSync(dir, { recursive: true });\n }\n const jsonPath = path.join(incidentsDir, `${id}.json`);\n const mdPath = path.join(incidentsDir, `${id}.md`);\n const jsonExists = fs.existsSync(jsonPath);\n const mdExists = fs.existsSync(mdPath);\n if ((jsonExists && (!regularFile(jsonPath) || fs.readFileSync(jsonPath, 'utf8') !== rawBody)) ||\n (mdExists && (!regularFile(mdPath) || !jsonExists))) {\n respond(409, { error: 'Conflict: incident ID exists with different content' }); return;\n }\n if (jsonExists && mdExists) {\n const latestId = publishLatest();\n retain(latestId);\n respond(200, { id, status: 'already_persisted' }); return;\n }\n const markdown = formatIncidentMarkdown(artifact);\n const header = `> **Artefato completo:** [\\`${id}.json\\`](incidents/${id}.json)\\n\\n`;\n if (Buffer.byteLength(rawBody) + 2 * Buffer.byteLength(markdown) + Buffer.byteLength(header) > maxStorageBytes) {\n respond(413, { error: 'Incident size exceeds maxStorageBytes limit' }); return;\n }\n const nonce = `${Date.now()}-${Math.random().toString(36).slice(2)}`;\n const tmpJson = `${jsonPath}.${nonce}.tmp`;\n const tmpMd = `${mdPath}.${nonce}.tmp`;\n let createdJson = false;\n let createdMd = false;\n try {\n if (!jsonExists) fs.writeFileSync(tmpJson, rawBody, { encoding: 'utf8', flag: 'wx' });\n fs.writeFileSync(tmpMd, markdown, { encoding: 'utf8', flag: 'wx' });\n if (!jsonExists) { fs.renameSync(tmpJson, jsonPath); createdJson = true; }\n fs.renameSync(tmpMd, mdPath); createdMd = true;\n publishLatest();\n } catch (error) {\n if (createdMd && regularFile(mdPath)) fs.unlinkSync(mdPath);\n if (createdJson && regularFile(jsonPath)) fs.unlinkSync(jsonPath);\n throw error;\n } finally {\n for (const file of [tmpJson, tmpMd]) if (regularFile(file)) fs.unlinkSync(file);\n }\n const list = scan();\n retain(list[list.length - 1].id);\n respond(201, { id, status: 'saved' });\n } catch {\n respond(500, { error: 'Failed to persist incident' });\n }\n });\n });\n };\n}\r\n"],"names":["SAFE_ID","RESERVED_ID","safeId","id","localHostname","name","localAddress","address","allowedRequest","req","origins","host","target","origin","source","compareIncidents","a","b","regularFile","file","fs","createBacktrackMiddleware","options","dir","path","baseDirectory","incidentsDir","latestPath","maxBodyBytes","maxIncidents","maxStorageBytes","value","_a","url","persistenceQueue","scan","list","jsonPath","mdPath","validated","validateFlightRecorderArtifact","publishLatest","latest","content","temporary","retain","latestId","count","size","total","item","res","next","respond","status","body","bytes","rejected","chunks","chunk","rawBody","parsed","artifact","jsonExists","mdExists","markdown","formatIncidentMarkdown","header","nonce","tmpJson","tmpMd","createdJson","createdMd","error"],"mappings":"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"}
|
package/dist/dev-server.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dev-server.js","sources":["../src/dev-server/middleware.ts"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from 'http';\nimport fs from 'fs';\nimport path from 'path';\nimport { validateFlightRecorderArtifact } from '../validation/validate';\nimport { formatIncidentMarkdown } from '../utils/markdown';\n\nexport interface BacktrackMiddlewareOptions {\n /** Absolute directory; use only one middleware instance per directory. */\n directory?: string;\n /** Alias for directory. */\n outputDir?: string;\n allowedOrigins?: string[];\n maxBodyBytes?: number;\n maxIncidents?: number;\n maxStorageBytes?: number;\n}\nexport type ConnectLikeMiddleware = (req: IncomingMessage, res: ServerResponse, next?: (err?: unknown) => void) => void;\nconst SAFE_ID = /^[a-zA-Z0-9_-]{1,128}$/;\nconst RESERVED_ID = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])$/i;\nconst safeId = (id: string) => SAFE_ID.test(id) && !RESERVED_ID.test(id);\nconst localHostname = (name: string) => ['localhost', '127.0.0.1', '[::1]'].includes(name.toLowerCase());\nconst localAddress = (address?: string) => address === '127.0.0.1' || address === '::1' || address === '::ffff:127.0.0.1';\nfunction allowedRequest(req: IncomingMessage, origins?: string[]): boolean {\n if (!localAddress(req.socket.remoteAddress)) return false;\n try {\n const host = req.headers.host;\n if (!host) return false;\n const target = new URL(`http://${host}`);\n if (target.host !== host.toLowerCase() || !localHostname(target.hostname)) return false;\n const origin = req.headers.origin;\n if (!origin) return !origins?.length;\n const source = new URL(origin);\n if (!['http:', 'https:'].includes(source.protocol) || !localHostname(source.hostname) || source.origin !== origin) return false;\n return origins?.length ? origins.includes(origin) : source.host === target.host;\n } catch {\n return false;\n }\n}\ninterface ManagedIncident {\n id: string;\n triggeredAt: number;\n jsonPath: string;\n mdPath: string;\n size: number;\n}\nconst compareIncidents = (a: ManagedIncident, b: ManagedIncident) =>\n a.triggeredAt - b.triggeredAt || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0);\nfunction regularFile(file: string): boolean {\n return fs.existsSync(file) && fs.lstatSync(file).isFile();\n}\n\nexport function createBacktrackMiddleware(options: BacktrackMiddlewareOptions): ConnectLikeMiddleware {\n const dir = options?.directory ?? options?.outputDir;\n if (!options || typeof dir !== 'string' || !path.isAbsolute(dir)) {\n throw new Error('[Backtrack dev-server] A opção \"directory\" (ou \"outputDir\") absoluta é obrigatória.');\n }\n const baseDirectory = path.resolve(dir);\n const incidentsDir = path.join(baseDirectory, 'incidents');\n const latestPath = path.join(baseDirectory, 'latest.md');\n const maxBodyBytes = options.maxBodyBytes ?? 50 * 1024 * 1024;\n const maxIncidents = options.maxIncidents ?? 20;\n const maxStorageBytes = options.maxStorageBytes ?? 200 * 1024 * 1024;\n for (const value of [maxBodyBytes, maxIncidents, maxStorageBytes]) {\n if (!Number.isSafeInteger(value) || value <= 0) throw new Error('Backtrack limits must be positive safe integers.');\n }\n if (options.allowedOrigins?.some(origin => {\n try {\n const url = new URL(origin);\n return !localHostname(url.hostname) || !['http:', 'https:'].includes(url.protocol) || url.origin !== origin;\n } catch { return true; }\n })) throw new Error('Backtrack origins must be local HTTP(S) origins.');\n\n // ponytail: synchronous local writes serialized per instance; use async IO if measured dev-server latency warrants it.\n let persistenceQueue = Promise.resolve();\n function scan(): ManagedIncident[] {\n const list: ManagedIncident[] = [];\n for (const file of fs.readdirSync(incidentsDir)) {\n if (!file.endsWith('.json')) continue;\n const id = file.slice(0, -5);\n if (!safeId(id)) continue;\n const jsonPath = path.join(incidentsDir, file);\n const mdPath = path.join(incidentsDir, `${id}.md`);\n try {\n if (!regularFile(jsonPath) || !regularFile(mdPath) || fs.statSync(jsonPath).size > maxBodyBytes) continue;\n const validated = validateFlightRecorderArtifact(JSON.parse(fs.readFileSync(jsonPath, 'utf8')));\n if (!validated.success || validated.data.incident.id !== id) continue;\n if (!fs.readFileSync(mdPath, 'utf8').startsWith('# Incidente Backtrack\\n')) continue;\n list.push({ id, jsonPath, mdPath, triggeredAt: validated.data.incident.triggeredAt, size: fs.statSync(jsonPath).size + fs.statSync(mdPath).size });\n } catch {\n // Unknown, incomplete or invalid files are never retention candidates.\n }\n }\n return list.sort(compareIncidents);\n }\n function publishLatest(): string {\n const list = scan();\n const latest = list[list.length - 1];\n if (!latest) throw new Error('No complete incident to publish');\n const content = `> **Artefato completo:** [\\`${latest.id}.json\\`](incidents/${latest.id}.json)\\n\\n` + fs.readFileSync(latest.mdPath, 'utf8');\n const temporary = `${latestPath}.${Date.now()}.tmp`;\n try {\n fs.writeFileSync(temporary, content, { encoding: 'utf8', flag: 'wx' });\n fs.renameSync(temporary, latestPath);\n } finally {\n if (regularFile(temporary)) fs.unlinkSync(temporary);\n }\n return latest.id;\n }\n function retain(latestId: string): void {\n const list = scan();\n let count = list.length;\n let size = list.reduce((total, item) => total + item.size, fs.statSync(latestPath).size);\n for (const item of list) {\n if (count <= maxIncidents && size <= maxStorageBytes) break;\n if (item.id === latestId) continue;\n fs.unlinkSync(item.mdPath);\n fs.unlinkSync(item.jsonPath);\n count--;\n size -= item.size;\n }\n }\n return (req, res, next) => {\n const respond = (status: number, body: Record<string, unknown>) => {\n if (!res.destroyed && !res.headersSent) {\n res.writeHead(status, { 'Content-Type': 'application/json', ...(status === 405 ? { Allow: 'POST' } : {}) });\n res.end(JSON.stringify(body));\n }\n };\n if ((req.url || '').split('?')[0] !== '/__backtrack/incident') {\n if (next) next(); else respond(404, { error: 'Not found' });\n return;\n }\n if (req.method !== 'POST') { respond(405, { error: 'Method Not Allowed' }); return; }\n if ((req.headers['content-type'] || '').split(';')[0].trim().toLowerCase() !== 'application/json') {\n respond(415, { error: 'Unsupported Media Type: application/json required' }); return;\n }\n if (!allowedRequest(req, options.allowedOrigins)) { respond(403, { error: 'Forbidden: invalid origin or non-local access' }); return; }\n let bytes = 0;\n let rejected = false;\n const chunks: Buffer[] = [];\n req.on('error', () => { rejected = true; chunks.length = 0; });\n req.on('aborted', () => { rejected = true; chunks.length = 0; });\n req.on('data', (chunk: Buffer) => {\n if (rejected) return;\n bytes += chunk.length;\n if (bytes > maxBodyBytes) {\n rejected = true;\n chunks.length = 0;\n res.setHeader('Connection', 'close');\n respond(413, { error: 'Payload Too Large' });\n // Drain without retaining data so the HTTP response can reach the client.\n } else chunks.push(chunk);\n });\n req.on('end', () => {\n if (rejected) return;\n const rawBody = Buffer.concat(chunks).toString('utf8');\n chunks.length = 0;\n let parsed: unknown;\n try { parsed = JSON.parse(rawBody); }\n catch { respond(400, { error: 'Invalid JSON' }); return; }\n const validated = validateFlightRecorderArtifact(parsed);\n if (!validated.success) { respond(400, { error: 'Invalid artifact schema' }); return; }\n const artifact = validated.data;\n const id = artifact.incident.id;\n if (!safeId(id)) { respond(400, { error: 'Invalid incident ID format' }); return; }\n persistenceQueue = persistenceQueue.then(() => {\n try {\n for (const dir of [baseDirectory, incidentsDir]) {\n if (fs.existsSync(dir) && !fs.lstatSync(dir).isDirectory()) throw new Error('Invalid output directory');\n fs.mkdirSync(dir, { recursive: true });\n }\n const jsonPath = path.join(incidentsDir, `${id}.json`);\n const mdPath = path.join(incidentsDir, `${id}.md`);\n const jsonExists = fs.existsSync(jsonPath);\n const mdExists = fs.existsSync(mdPath);\n if ((jsonExists && (!regularFile(jsonPath) || fs.readFileSync(jsonPath, 'utf8') !== rawBody)) ||\n (mdExists && (!regularFile(mdPath) || !jsonExists))) {\n respond(409, { error: 'Conflict: incident ID exists with different content' }); return;\n }\n if (jsonExists && mdExists) {\n const latestId = publishLatest();\n retain(latestId);\n respond(200, { id, status: 'already_persisted' }); return;\n }\n const markdown = formatIncidentMarkdown(artifact);\n const header = `> **Artefato completo:** [\\`${id}.json\\`](incidents/${id}.json)\\n\\n`;\n if (Buffer.byteLength(rawBody) + 2 * Buffer.byteLength(markdown) + Buffer.byteLength(header) > maxStorageBytes) {\n respond(413, { error: 'Incident size exceeds maxStorageBytes limit' }); return;\n }\n const nonce = `${Date.now()}-${Math.random().toString(36).slice(2)}`;\n const tmpJson = `${jsonPath}.${nonce}.tmp`;\n const tmpMd = `${mdPath}.${nonce}.tmp`;\n let createdJson = false;\n let createdMd = false;\n try {\n if (!jsonExists) fs.writeFileSync(tmpJson, rawBody, { encoding: 'utf8', flag: 'wx' });\n fs.writeFileSync(tmpMd, markdown, { encoding: 'utf8', flag: 'wx' });\n if (!jsonExists) { fs.renameSync(tmpJson, jsonPath); createdJson = true; }\n fs.renameSync(tmpMd, mdPath); createdMd = true;\n publishLatest();\n } catch (error) {\n if (createdMd && regularFile(mdPath)) fs.unlinkSync(mdPath);\n if (createdJson && regularFile(jsonPath)) fs.unlinkSync(jsonPath);\n throw error;\n } finally {\n for (const file of [tmpJson, tmpMd]) if (regularFile(file)) fs.unlinkSync(file);\n }\n const list = scan();\n retain(list[list.length - 1].id);\n respond(201, { id, status: 'saved' });\n } catch {\n respond(500, { error: 'Failed to persist incident' });\n }\n });\n });\n };\n}\r\n"],"names":["SAFE_ID","RESERVED_ID","safeId","id","localHostname","name","localAddress","address","allowedRequest","req","origins","host","target","origin","source","compareIncidents","a","b","regularFile","file","fs","createBacktrackMiddleware","options","dir","path","baseDirectory","incidentsDir","latestPath","maxBodyBytes","maxIncidents","maxStorageBytes","value","_a","url","persistenceQueue","scan","list","jsonPath","mdPath","validated","validateFlightRecorderArtifact","publishLatest","latest","content","temporary","retain","latestId","count","size","total","item","res","next","respond","status","body","bytes","rejected","chunks","chunk","rawBody","parsed","artifact","jsonExists","mdExists","markdown","formatIncidentMarkdown","header","nonce","tmpJson","tmpMd","createdJson","createdMd","error"],"mappings":";;;AAiBA,MAAMA,IAAU,0BACVC,IAAc,0CACdC,IAAS,CAACC,MAAeH,EAAQ,KAAKG,CAAE,KAAK,CAACF,EAAY,KAAKE,CAAE,GACjEC,IAAgB,CAACC,MAAiB,CAAC,aAAa,aAAa,OAAO,EAAE,SAASA,EAAK,aAAa,GACjGC,IAAe,CAACC,MAAqBA,MAAY,eAAeA,MAAY,SAASA,MAAY;AACvG,SAASC,EAAeC,GAAsBC,GAA6B;AACzE,MAAI,CAACJ,EAAaG,EAAI,OAAO,aAAa,EAAG,QAAO;AACpD,MAAI;AACF,UAAME,IAAOF,EAAI,QAAQ;AACzB,QAAI,CAACE,EAAM,QAAO;AAClB,UAAMC,IAAS,IAAI,IAAI,UAAUD,CAAI,EAAE;AACvC,QAAIC,EAAO,SAASD,EAAK,YAAA,KAAiB,CAACP,EAAcQ,EAAO,QAAQ,EAAG,QAAO;AAClF,UAAMC,IAASJ,EAAI,QAAQ;AAC3B,QAAI,CAACI,EAAQ,QAAO,EAACH,KAAA,QAAAA,EAAS;AAC9B,UAAMI,IAAS,IAAI,IAAID,CAAM;AAC7B,WAAI,CAAC,CAAC,SAAS,QAAQ,EAAE,SAASC,EAAO,QAAQ,KAAK,CAACV,EAAcU,EAAO,QAAQ,KAAKA,EAAO,WAAWD,IAAe,KACnHH,KAAA,QAAAA,EAAS,SAASA,EAAQ,SAASG,CAAM,IAAIC,EAAO,SAASF,EAAO;AAAA,EAC7E,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAQA,MAAMG,IAAmB,CAACC,GAAoBC,MAC5CD,EAAE,cAAcC,EAAE,gBAAgBD,EAAE,KAAKC,EAAE,KAAK,KAAKD,EAAE,KAAKC,EAAE,KAAK,IAAI;AACzE,SAASC,EAAYC,GAAuB;AAC1C,SAAOC,EAAG,WAAWD,CAAI,KAAKC,EAAG,UAAUD,CAAI,EAAE,OAAA;AACnD;AAEO,SAASE,EAA0BC,GAA4D;;AACpG,QAAMC,KAAMD,KAAA,gBAAAA,EAAS,eAAaA,KAAA,gBAAAA,EAAS;AAC3C,MAAI,CAACA,KAAW,OAAOC,KAAQ,YAAY,CAACC,EAAK,WAAWD,CAAG;AAC7D,UAAM,IAAI,MAAM,qFAAqF;AAEvG,QAAME,IAAgBD,EAAK,QAAQD,CAAG,GAChCG,IAAeF,EAAK,KAAKC,GAAe,WAAW,GACnDE,IAAaH,EAAK,KAAKC,GAAe,WAAW,GACjDG,IAAeN,EAAQ,gBAAgB,KAAK,OAAO,MACnDO,IAAeP,EAAQ,gBAAgB,IACvCQ,IAAkBR,EAAQ,mBAAmB,MAAM,OAAO;AAChE,aAAWS,KAAS,CAACH,GAAcC,GAAcC,CAAe;AAC9D,QAAI,CAAC,OAAO,cAAcC,CAAK,KAAKA,KAAS,EAAG,OAAM,IAAI,MAAM,kDAAkD;AAEpH,OAAIC,IAAAV,EAAQ,mBAAR,QAAAU,EAAwB,KAAK,CAAAnB,MAAU;AACzC,QAAI;AACF,YAAMoB,IAAM,IAAI,IAAIpB,CAAM;AAC1B,aAAO,CAACT,EAAc6B,EAAI,QAAQ,KAAK,CAAC,CAAC,SAAS,QAAQ,EAAE,SAASA,EAAI,QAAQ,KAAKA,EAAI,WAAWpB;AAAA,IACvG,QAAQ;AAAE,aAAO;AAAA,IAAM;AAAA,EACzB,GAAI,OAAM,IAAI,MAAM,kDAAkD;AAGtE,MAAIqB,IAAmB,QAAQ,QAAA;AAC/B,WAASC,IAA0B;AACjC,UAAMC,IAA0B,CAAA;AAChC,eAAWjB,KAAQC,EAAG,YAAYM,CAAY,GAAG;AAC/C,UAAI,CAACP,EAAK,SAAS,OAAO,EAAG;AAC7B,YAAMhB,IAAKgB,EAAK,MAAM,GAAG,EAAE;AAC3B,UAAI,CAACjB,EAAOC,CAAE,EAAG;AACjB,YAAMkC,IAAWb,EAAK,KAAKE,GAAcP,CAAI,GACvCmB,IAASd,EAAK,KAAKE,GAAc,GAAGvB,CAAE,KAAK;AACjD,UAAI;AACF,YAAI,CAACe,EAAYmB,CAAQ,KAAK,CAACnB,EAAYoB,CAAM,KAAKlB,EAAG,SAASiB,CAAQ,EAAE,OAAOT,EAAc;AACjG,cAAMW,IAAYC,EAA+B,KAAK,MAAMpB,EAAG,aAAaiB,GAAU,MAAM,CAAC,CAAC;AAE9F,YADI,CAACE,EAAU,WAAWA,EAAU,KAAK,SAAS,OAAOpC,KACrD,CAACiB,EAAG,aAAakB,GAAQ,MAAM,EAAE,WAAW;AAAA,CAAyB,EAAG;AAC5E,QAAAF,EAAK,KAAK,EAAE,IAAAjC,GAAI,UAAAkC,GAAU,QAAAC,GAAQ,aAAaC,EAAU,KAAK,SAAS,aAAa,MAAMnB,EAAG,SAASiB,CAAQ,EAAE,OAAOjB,EAAG,SAASkB,CAAM,EAAE,MAAM;AAAA,MACnJ,QAAQ;AAAA,MAER;AAAA,IACF;AACA,WAAOF,EAAK,KAAKrB,CAAgB;AAAA,EACnC;AACA,WAAS0B,IAAwB;AAC/B,UAAML,IAAOD,EAAA,GACPO,IAASN,EAAKA,EAAK,SAAS,CAAC;AACnC,QAAI,CAACM,EAAQ,OAAM,IAAI,MAAM,iCAAiC;AAC9D,UAAMC,IAAU,+BAA+BD,EAAO,EAAE,sBAAsBA,EAAO,EAAE;AAAA;AAAA,IAAetB,EAAG,aAAasB,EAAO,QAAQ,MAAM,GACrIE,IAAY,GAAGjB,CAAU,IAAI,KAAK,KAAK;AAC7C,QAAI;AACF,MAAAP,EAAG,cAAcwB,GAAWD,GAAS,EAAE,UAAU,QAAQ,MAAM,MAAM,GACrEvB,EAAG,WAAWwB,GAAWjB,CAAU;AAAA,IACrC,UAAA;AACE,MAAIT,EAAY0B,CAAS,KAAGxB,EAAG,WAAWwB,CAAS;AAAA,IACrD;AACA,WAAOF,EAAO;AAAA,EAChB;AACA,WAASG,EAAOC,GAAwB;AACtC,UAAMV,IAAOD,EAAA;AACb,QAAIY,IAAQX,EAAK,QACbY,IAAOZ,EAAK,OAAO,CAACa,GAAOC,MAASD,IAAQC,EAAK,MAAM9B,EAAG,SAASO,CAAU,EAAE,IAAI;AACvF,eAAWuB,KAAQd,GAAM;AACvB,UAAIW,KAASlB,KAAgBmB,KAAQlB,EAAiB;AACtD,MAAIoB,EAAK,OAAOJ,MAChB1B,EAAG,WAAW8B,EAAK,MAAM,GACzB9B,EAAG,WAAW8B,EAAK,QAAQ,GAC3BH,KACAC,KAAQE,EAAK;AAAA,IACf;AAAA,EACF;AACA,SAAO,CAACzC,GAAK0C,GAAKC,MAAS;AACzB,UAAMC,IAAU,CAACC,GAAgBC,MAAkC;AACjE,MAAI,CAACJ,EAAI,aAAa,CAACA,EAAI,gBACzBA,EAAI,UAAUG,GAAQ,EAAE,gBAAgB,oBAAoB,GAAIA,MAAW,MAAM,EAAE,OAAO,OAAA,IAAW,CAAA,GAAK,GAC1GH,EAAI,IAAI,KAAK,UAAUI,CAAI,CAAC;AAAA,IAEhC;AACA,SAAK9C,EAAI,OAAO,IAAI,MAAM,GAAG,EAAE,CAAC,MAAM,yBAAyB;AAC7D,MAAI2C,IAAMA,EAAA,IAAaC,EAAQ,KAAK,EAAE,OAAO,aAAa;AAC1D;AAAA,IACF;AACA,QAAI5C,EAAI,WAAW,QAAQ;AAAE,MAAA4C,EAAQ,KAAK,EAAE,OAAO,qBAAA,CAAsB;AAAG;AAAA,IAAQ;AACpF,SAAK5C,EAAI,QAAQ,cAAc,KAAK,IAAI,MAAM,GAAG,EAAE,CAAC,EAAE,KAAA,EAAO,YAAA,MAAkB,oBAAoB;AACjG,MAAA4C,EAAQ,KAAK,EAAE,OAAO,oDAAA,CAAqD;AAAG;AAAA,IAChF;AACA,QAAI,CAAC7C,EAAeC,GAAKa,EAAQ,cAAc,GAAG;AAAE,MAAA+B,EAAQ,KAAK,EAAE,OAAO,gDAAA,CAAiD;AAAG;AAAA,IAAQ;AACtI,QAAIG,IAAQ,GACRC,IAAW;AACf,UAAMC,IAAmB,CAAA;AACzB,IAAAjD,EAAI,GAAG,SAAS,MAAM;AAAE,MAAAgD,IAAW,IAAMC,EAAO,SAAS;AAAA,IAAG,CAAC,GAC7DjD,EAAI,GAAG,WAAW,MAAM;AAAE,MAAAgD,IAAW,IAAMC,EAAO,SAAS;AAAA,IAAG,CAAC,GAC/DjD,EAAI,GAAG,QAAQ,CAACkD,MAAkB;AAChC,MAAIF,MACJD,KAASG,EAAM,QACXH,IAAQ5B,KACV6B,IAAW,IACXC,EAAO,SAAS,GAChBP,EAAI,UAAU,cAAc,OAAO,GACnCE,EAAQ,KAAK,EAAE,OAAO,oBAAA,CAAqB,KAEtCK,EAAO,KAAKC,CAAK;AAAA,IAC1B,CAAC,GACDlD,EAAI,GAAG,OAAO,MAAM;AAClB,UAAIgD,EAAU;AACd,YAAMG,IAAU,OAAO,OAAOF,CAAM,EAAE,SAAS,MAAM;AACrD,MAAAA,EAAO,SAAS;AAChB,UAAIG;AACJ,UAAI;AAAE,QAAAA,IAAS,KAAK,MAAMD,CAAO;AAAA,MAAG,QAC9B;AAAE,QAAAP,EAAQ,KAAK,EAAE,OAAO,eAAA,CAAgB;AAAG;AAAA,MAAQ;AACzD,YAAMd,IAAYC,EAA+BqB,CAAM;AACvD,UAAI,CAACtB,EAAU,SAAS;AAAE,QAAAc,EAAQ,KAAK,EAAE,OAAO,0BAAA,CAA2B;AAAG;AAAA,MAAQ;AACtF,YAAMS,IAAWvB,EAAU,MACrBpC,IAAK2D,EAAS,SAAS;AAC7B,UAAI,CAAC5D,EAAOC,CAAE,GAAG;AAAE,QAAAkD,EAAQ,KAAK,EAAE,OAAO,6BAAA,CAA8B;AAAG;AAAA,MAAQ;AAClF,MAAAnB,IAAmBA,EAAiB,KAAK,MAAM;AAC7C,YAAI;AACF,qBAAWX,KAAO,CAACE,GAAeC,CAAY,GAAG;AAC/C,gBAAIN,EAAG,WAAWG,CAAG,KAAK,CAACH,EAAG,UAAUG,CAAG,EAAE,YAAA,EAAe,OAAM,IAAI,MAAM,0BAA0B;AACtG,YAAAH,EAAG,UAAUG,GAAK,EAAE,WAAW,IAAM;AAAA,UACvC;AACA,gBAAMc,IAAWb,EAAK,KAAKE,GAAc,GAAGvB,CAAE,OAAO,GAC/CmC,IAASd,EAAK,KAAKE,GAAc,GAAGvB,CAAE,KAAK,GAC3C4D,IAAa3C,EAAG,WAAWiB,CAAQ,GACnC2B,IAAW5C,EAAG,WAAWkB,CAAM;AACrC,cAAKyB,MAAe,CAAC7C,EAAYmB,CAAQ,KAAKjB,EAAG,aAAaiB,GAAU,MAAM,MAAMuB,MAC/EI,MAAa,CAAC9C,EAAYoB,CAAM,KAAK,CAACyB,IAAc;AACvD,YAAAV,EAAQ,KAAK,EAAE,OAAO,sDAAA,CAAuD;AAAG;AAAA,UAClF;AACA,cAAIU,KAAcC,GAAU;AAC1B,kBAAMlB,IAAWL,EAAA;AACjB,YAAAI,EAAOC,CAAQ,GACfO,EAAQ,KAAK,EAAE,IAAAlD,GAAI,QAAQ,qBAAqB;AAAG;AAAA,UACrD;AACA,gBAAM8D,IAAWC,EAAuBJ,CAAQ,GAC1CK,IAAS,+BAA+BhE,CAAE,sBAAsBA,CAAE;AAAA;AAAA;AACxE,cAAI,OAAO,WAAWyD,CAAO,IAAI,IAAI,OAAO,WAAWK,CAAQ,IAAI,OAAO,WAAWE,CAAM,IAAIrC,GAAiB;AAC9G,YAAAuB,EAAQ,KAAK,EAAE,OAAO,8CAAA,CAA+C;AAAG;AAAA,UAC1E;AACA,gBAAMe,IAAQ,GAAG,KAAK,IAAA,CAAK,IAAI,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC,IAC5DC,IAAU,GAAGhC,CAAQ,IAAI+B,CAAK,QAC9BE,IAAQ,GAAGhC,CAAM,IAAI8B,CAAK;AAChC,cAAIG,IAAc,IACdC,IAAY;AAChB,cAAI;AACF,YAAKT,KAAY3C,EAAG,cAAciD,GAAST,GAAS,EAAE,UAAU,QAAQ,MAAM,KAAA,CAAM,GACpFxC,EAAG,cAAckD,GAAOL,GAAU,EAAE,UAAU,QAAQ,MAAM,MAAM,GAC7DF,MAAc3C,EAAG,WAAWiD,GAAShC,CAAQ,GAAGkC,IAAc,KACnEnD,EAAG,WAAWkD,GAAOhC,CAAM,GAAGkC,IAAY,IAC1C/B,EAAA;AAAA,UACF,SAASgC,GAAO;AACd,kBAAID,KAAatD,EAAYoB,CAAM,KAAGlB,EAAG,WAAWkB,CAAM,GACtDiC,KAAerD,EAAYmB,CAAQ,KAAGjB,EAAG,WAAWiB,CAAQ,GAC1DoC;AAAA,UACR,UAAA;AACE,uBAAWtD,KAAQ,CAACkD,GAASC,CAAK,EAAG,CAAIpD,EAAYC,CAAI,KAAGC,EAAG,WAAWD,CAAI;AAAA,UAChF;AACA,gBAAMiB,IAAOD,EAAA;AACb,UAAAU,EAAOT,EAAKA,EAAK,SAAS,CAAC,EAAE,EAAE,GAC/BiB,EAAQ,KAAK,EAAE,IAAAlD,GAAI,QAAQ,SAAS;AAAA,QACtC,QAAQ;AACN,UAAAkD,EAAQ,KAAK,EAAE,OAAO,6BAAA,CAA8B;AAAA,QACtD;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AACF;"}
|