@backtrack-js/browser 0.4.2 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +507 -364
- package/bin/symbolize.cjs +205 -62
- package/dev-server/package.json +6 -0
- package/dist/dev-server/index.d.ts +2 -0
- package/dist/dev-server/index.d.ts.map +1 -0
- package/dist/dev-server/middleware.d.ts +14 -0
- package/dist/dev-server/middleware.d.ts.map +1 -0
- package/dist/dev-server.cjs +7 -0
- package/dist/dev-server.cjs.map +1 -0
- package/dist/dev-server.js +173 -0
- package/dist/dev-server.js.map +1 -0
- package/dist/index.cjs +41 -42
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1724 -2043
- package/dist/index.js.map +1 -1
- package/dist/markdown-Ao5Ah9MF.cjs +9 -0
- package/dist/markdown-Ao5Ah9MF.cjs.map +1 -0
- package/dist/markdown-D3C94OlY.js +494 -0
- package/dist/markdown-D3C94OlY.js.map +1 -0
- package/dist/types/timeline.d.ts +3 -2
- package/dist/types/timeline.d.ts.map +1 -1
- package/dist/utils/markdown.d.ts +11 -3
- package/dist/utils/markdown.d.ts.map +1 -1
- package/dist/validation/validate.d.ts.map +1 -1
- package/dist/viewer/assets/index-C3SZvpLL.js +197 -0
- package/dist/viewer/assets/{index-cVrM07fr.css → index-CKVr0pQ5.css} +1 -1
- package/dist/viewer/index.html +2 -2
- package/package.json +7 -1
- package/dist/viewer/assets/index-BXa4ZYfb.js +0 -191
|
@@ -0,0 +1 @@
|
|
|
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":"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"}
|