@willbooster/shared-lib 10.17.0 → 10.19.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.
Files changed (103) hide show
  1. package/dist/array.cjs +2 -0
  2. package/dist/array.cjs.map +1 -0
  3. package/dist/array.d.ts +2 -0
  4. package/dist/array.js +2 -0
  5. package/dist/array.js.map +1 -0
  6. package/dist/concurrency.cjs +1 -1
  7. package/dist/concurrency.cjs.map +1 -1
  8. package/dist/concurrency.d.ts +5 -1
  9. package/dist/concurrency.js +1 -1
  10. package/dist/concurrency.js.map +1 -1
  11. package/dist/crypto.cjs +2 -0
  12. package/dist/crypto.cjs.map +1 -0
  13. package/dist/crypto.d.ts +11 -0
  14. package/dist/crypto.js +2 -0
  15. package/dist/crypto.js.map +1 -0
  16. package/dist/error.cjs +2 -2
  17. package/dist/error.cjs.map +1 -1
  18. package/dist/error.d.ts +9 -0
  19. package/dist/error.js +2 -2
  20. package/dist/error.js.map +1 -1
  21. package/dist/filePath.cjs +2 -0
  22. package/dist/filePath.cjs.map +1 -0
  23. package/dist/filePath.d.ts +5 -0
  24. package/dist/filePath.js +2 -0
  25. package/dist/filePath.js.map +1 -0
  26. package/dist/foreignCjk.cjs +1 -1
  27. package/dist/foreignCjk.cjs.map +1 -1
  28. package/dist/foreignCjk.js +1 -1
  29. package/dist/foreignCjk.js.map +1 -1
  30. package/dist/formatIsoDate.cjs +2 -0
  31. package/dist/formatIsoDate.cjs.map +1 -0
  32. package/dist/formatIsoDate.d.ts +7 -0
  33. package/dist/formatIsoDate.js +2 -0
  34. package/dist/formatIsoDate.js.map +1 -0
  35. package/dist/github.cjs +2 -0
  36. package/dist/github.cjs.map +1 -0
  37. package/dist/github.d.ts +8 -0
  38. package/dist/github.js +2 -0
  39. package/dist/github.js.map +1 -0
  40. package/dist/http.cjs +2 -0
  41. package/dist/http.cjs.map +1 -0
  42. package/dist/http.d.ts +7 -0
  43. package/dist/http.js +2 -0
  44. package/dist/http.js.map +1 -0
  45. package/dist/humanize.cjs +1 -1
  46. package/dist/humanize.cjs.map +1 -1
  47. package/dist/humanize.d.ts +5 -0
  48. package/dist/humanize.js +1 -1
  49. package/dist/humanize.js.map +1 -1
  50. package/dist/index.cjs +1 -1
  51. package/dist/index.d.ts +16 -5
  52. package/dist/index.js +1 -1
  53. package/dist/markdown.cjs +1 -1
  54. package/dist/markdown.cjs.map +1 -1
  55. package/dist/markdown.js +1 -1
  56. package/dist/markdown.js.map +1 -1
  57. package/dist/number.cjs +2 -0
  58. package/dist/number.cjs.map +1 -0
  59. package/dist/number.d.ts +7 -0
  60. package/dist/number.js +2 -0
  61. package/dist/number.js.map +1 -0
  62. package/dist/object.cjs +2 -0
  63. package/dist/object.cjs.map +1 -0
  64. package/dist/object.d.ts +16 -0
  65. package/dist/object.js +2 -0
  66. package/dist/object.js.map +1 -0
  67. package/dist/parseIsoDate.cjs +1 -1
  68. package/dist/parseIsoDate.cjs.map +1 -1
  69. package/dist/parseIsoDate.js +1 -1
  70. package/dist/parseIsoDate.js.map +1 -1
  71. package/dist/prompt.cjs +2 -2
  72. package/dist/prompt.cjs.map +1 -1
  73. package/dist/prompt.js +10 -10
  74. package/dist/prompt.js.map +1 -1
  75. package/dist/promptFormatters.cjs +1 -1
  76. package/dist/promptFormatters.cjs.map +1 -1
  77. package/dist/promptFormatters.js +1 -1
  78. package/dist/promptFormatters.js.map +1 -1
  79. package/dist/recoverJson.cjs +2 -2
  80. package/dist/recoverJson.cjs.map +1 -1
  81. package/dist/recoverJson.js +2 -1
  82. package/dist/recoverJson.js.map +1 -1
  83. package/dist/sqlite.cjs +1 -1
  84. package/dist/sqlite.cjs.map +1 -1
  85. package/dist/sqlite.d.ts +7 -0
  86. package/dist/sqlite.js +1 -1
  87. package/dist/sqlite.js.map +1 -1
  88. package/dist/text.cjs +1 -1
  89. package/dist/text.cjs.map +1 -1
  90. package/dist/text.d.ts +12 -0
  91. package/dist/text.js +1 -1
  92. package/dist/text.js.map +1 -1
  93. package/dist/timeout.cjs +2 -0
  94. package/dist/timeout.cjs.map +1 -0
  95. package/dist/timeout.d.ts +12 -0
  96. package/dist/timeout.js +2 -0
  97. package/dist/timeout.js.map +1 -0
  98. package/dist/yaml.cjs +2 -0
  99. package/dist/yaml.cjs.map +1 -0
  100. package/dist/yaml.d.ts +8 -0
  101. package/dist/yaml.js +2 -0
  102. package/dist/yaml.js.map +1 -0
  103. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"recoverJson.js","names":[],"sources":["../src/recoverJson.ts"],"sourcesContent":["/*! JSON recovery informed by jsonrepair, Copyright (c) 2020-2026 Jos de Jong (ISC). See NOTICE. */\n\nexport interface JsonRepair {\n /** UTF-16 offset in the original response. */\n offset: number;\n kind: 'syntax' | 'incomplete' | 'ambiguous';\n reason: string;\n}\n\nexport interface RecoveredJson {\n value: unknown;\n json: string;\n start: number;\n end: number;\n repairs: JsonRepair[];\n /** Missing content or an ambiguous interpretation requires confirmation before acting on this value. */\n requiresConfirmation: boolean;\n}\n\nexport interface JsonRecovery {\n candidates: RecoveredJson[];\n errors: { offset: number; message: string }[];\n}\n\nconst MAX_INPUT_LENGTH = 1_000_000;\nconst MAX_DEPTH = 128;\nconst MAX_CANDIDATES = 32;\nconst MAX_ERRORS = 32;\nconst MAX_DIAGNOSTIC_EXCERPT = 256;\nconst QUOTES: Record<string, string> = { '\"': '\"', \"'\": \"'\", '“': '”', '”': '”', '‘': '’', '’': '’' };\nconst KEYWORDS: Record<string, string> = {\n true: 'true',\n false: 'false',\n null: 'null',\n True: 'true',\n False: 'false',\n None: 'null',\n};\n\n/**\n * Extracts JSON values from a response, repairing common LLM syntax and retaining repair provenance.\n * Offsets refer to the original string. All candidates are returned: choosing among multiple answers,\n * schema validation, and provider truncation signals belong to the caller. No schema values are coerced.\n * Bounded to one million UTF-16 code units, 128 nesting levels, and 32 candidates/errors each.\n * A region is abandoned after 32 failed starts; later Markdown regions can still yield candidates.\n */\nexport function recoverJson(text: string): JsonRecovery {\n const result: JsonRecovery = { candidates: [], errors: [] };\n if (text.length > MAX_INPUT_LENGTH) {\n result.errors.push({ offset: MAX_INPUT_LENGTH, message: 'JSON recovery input exceeds one million characters' });\n return result;\n }\n const fences = [...text.matchAll(/^(?: {0,3})(`{3,}|~{3,})[^\\r\\n]*(?:\\r\\n|[\\r\\n]|$)/gm)].flatMap((fence) => {\n const marker = fence[1]!;\n const markerEnd = fence.index + fence[0].indexOf(marker) + marker.length;\n const lineEnd = fence.index + fence[0].length;\n const info = text.slice(markerEnd, lineEnd);\n const inlinePrefix = /^[ \\t]*json(?=[ \\t{[\"'“”‘’])[ \\t]*/i.exec(info);\n const inlineStart = inlinePrefix === null ? lineEnd : markerEnd + inlinePrefix[0].length;\n const start =\n text[inlineStart] === '{' || text[inlineStart] === '[' || scalarStart(text, inlineStart, lineEnd)\n ? inlineStart\n : lineEnd;\n return marker[0] === '`' && start === lineEnd && info.includes('`') ? [] : [{ index: fence.index, marker, start }];\n });\n if (fences.length > 0) {\n let consumed = 0;\n for (const fence of fences) {\n if (fence.index < consumed) continue;\n extractRegion(text, consumed, fence.index, result);\n const parsedThrough = result.candidates.at(-1)?.end ?? consumed;\n if (parsedThrough > fence.index) {\n consumed = parsedThrough;\n continue;\n }\n const { marker, start } = fence;\n const close = new RegExp(`^ {0,3}${marker[0]}{${marker.length},}[ \\\\t]*$`, 'gm');\n close.lastIndex = start;\n const match = close.exec(text);\n const end = match?.index ?? text.length;\n extractRegion(text, start, end, result);\n const extendedEnd = result.candidates.at(-1)?.end ?? start;\n if (extendedEnd > end) {\n close.lastIndex = extendedEnd;\n const outerClose = close.exec(text);\n if (outerClose !== null && !fences.some((next) => next.index >= extendedEnd && next.index < outerClose.index)) {\n extractRegion(text, extendedEnd, outerClose.index, result);\n consumed = outerClose.index + outerClose[0].length;\n continue;\n }\n }\n consumed = Math.max(\n result.candidates.at(-1)?.end ?? start,\n match === null ? text.length : match.index + match[0].length\n );\n }\n extractRegion(text, consumed, text.length, result);\n } else {\n extractRegion(text, 0, text.length, result);\n }\n if (result.candidates.length === MAX_CANDIDATES) {\n const error = {\n offset: result.candidates.at(-1)!.end,\n message: 'JSON candidate limit reached; extraction may be incomplete',\n };\n if (result.errors.length === MAX_ERRORS) result.errors[MAX_ERRORS - 1] = error;\n else result.errors.push(error);\n }\n return result;\n}\n\nfunction extractRegion(text: string, start: number, end: number, result: JsonRecovery, commentFragment = false): void {\n if (result.candidates.length >= MAX_CANDIDATES) return;\n let index = start;\n let failures = 0;\n let ambiguousScalarTail = false;\n let scalarBoundary = true;\n let uriBoundaryEnd = start;\n let uriTokenEnd = start;\n let uriContainerStart = start;\n while (index < end && /\\s/.test(text[index]!)) index++;\n const firstIndex = index;\n const initialParser = new RecoveryParser(text, index, end);\n if (!commentFragment) initialParser.space();\n const initialValueStart = initialParser.index;\n if (initialValueStart >= end) {\n if (initialParser.repairs.some((repair) => repair.kind === 'incomplete') && result.errors.length < MAX_ERRORS)\n result.errors.push({ offset: index, message: 'Incomplete leading JSON comment' });\n return;\n }\n const first = text[initialValueStart];\n // Within prose, scalar starts need a line boundary; containers may appear inline.\n const rootValue = scalarStart(text, initialValueStart, end);\n const initialValue = rootValue || first === '{' || first === '[';\n if (!initialValue) index = initialValueStart;\n while (index < end && result.candidates.length < MAX_CANDIDATES && failures < MAX_ERRORS) {\n if (!initialValue || index !== firstIndex) {\n while (index < end && text[index] !== '{' && text[index] !== '[') {\n if (scalarBoundary && scalarStart(text, index, end)) break;\n const uriEnd =\n index === start || !/[\\w+.-]/.test(text[index - 1]!) ? unquotedUriEnd(text, index, end) : undefined;\n if (uriEnd !== undefined) {\n if (index >= uriTokenEnd) {\n const whitespace = text.slice(index, end).search(/\\s/);\n uriTokenEnd = whitespace === -1 ? end : index + whitespace;\n uriContainerStart = index;\n }\n if (index >= uriContainerStart) {\n const container = text.slice(index, uriTokenEnd).search(/[{[]/);\n uriContainerStart = container === -1 ? uriTokenEnd : index + container;\n }\n if (uriContainerStart < uriTokenEnd) uriBoundaryEnd = Math.max(uriBoundaryEnd, uriTokenEnd);\n index = Math.min(uriEnd, uriContainerStart);\n scalarBoundary = false;\n continue;\n }\n if (!commentFragment && text[index] === '/') {\n const trivia = new RecoveryParser(text, index, end);\n trivia.space();\n if (trivia.index > index) {\n if (trivia.repairs.some((repair) => repair.kind === 'incomplete') && result.errors.length < MAX_ERRORS)\n result.errors.push({ offset: index, message: 'Possibly unterminated comment-like span in prose' });\n extractRegion(text, index + 2, trivia.index, result, true);\n scalarBoundary ||= /[\\r\\n]/.test(text.slice(index, trivia.index));\n index = trivia.index;\n continue;\n }\n }\n if (/[\\r\\n]/.test(text[index]!)) scalarBoundary = true;\n else if (!/[\\s,]/.test(text[index]!)) scalarBoundary = false;\n index++;\n }\n }\n if (index >= end || result.candidates.length >= MAX_CANDIDATES) break;\n let parser = initialValue && index === firstIndex ? initialParser : new RecoveryParser(text, index, end);\n const valueStart = parser.index;\n try {\n let json = parser.value(0);\n if (\n !commentFragment &&\n (text[valueStart] === '{' || text[valueStart] === '[') &&\n parser.index === end &&\n end < text.length\n ) {\n const extended = new RecoveryParser(text, index, text.length);\n try {\n const extendedJson = extended.value(0);\n if (\n extended.index > end &&\n extended.repairs.every((repair) => repair.reason === 'unescaped-control-character')\n ) {\n extended.repairs.push({ offset: end, kind: 'ambiguous', reason: 'literal-fence-in-string' });\n parser = extended;\n json = extendedJson;\n }\n } catch {\n // Keep the bounded interpretation when extending it is not a complete JSON document.\n }\n }\n const valueEnd = parser.index;\n if (text[valueStart] !== '{' && text[valueStart] !== '[' && !parser.finishScalar(end, valueStart)) {\n scalarBoundary = false;\n index = valueEnd;\n continue;\n }\n parser.space();\n if (!commentFragment && failures === 0 && parser.index < end && /[}\\]]/.test(text[parser.index]!)) {\n const surplusStart = parser.index;\n while (parser.index < end && /[}\\]]/.test(text[parser.index]!)) {\n parser.repairs.push({ offset: parser.index, kind: 'ambiguous', reason: 'surplus-closing-bracket' });\n parser.index++;\n parser.space();\n }\n if (result.errors.length < MAX_ERRORS) {\n const excerptEnd = Math.min(end, surplusStart + MAX_DIAGNOSTIC_EXCERPT);\n result.errors.push({\n offset: surplusStart,\n message: `Surplus closing brackets and possible continuation (${excerptEnd < end ? 'truncated excerpt' : 'excerpt'}): ${JSON.stringify(text.slice(surplusStart, excerptEnd))}`,\n });\n }\n }\n if (\n text[valueStart]! in QUOTES &&\n parser.repairs.some((repair) => repair.reason === 'trailing-scalar-content') &&\n result.errors.length < MAX_ERRORS\n ) {\n const excerptEnd = Math.min(end, valueEnd + MAX_DIAGNOSTIC_EXCERPT);\n result.errors.push({\n offset: valueEnd,\n message: `Ambiguous quoted-scalar tail (${excerptEnd < end ? 'truncated excerpt' : 'excerpt'}): ${JSON.stringify(text.slice(valueEnd, excerptEnd))}`,\n });\n }\n if (commentFragment)\n parser.repairs.unshift({ offset: index, kind: 'ambiguous', reason: 'fragment-in-comment-like-prose' });\n if (failures > 0)\n parser.repairs.unshift({ offset: index, kind: 'ambiguous', reason: 'fragment-after-rejected-document' });\n if (ambiguousScalarTail)\n parser.repairs.unshift({ offset: index, kind: 'ambiguous', reason: 'fragment-after-ambiguous-scalar' });\n if (index < uriBoundaryEnd)\n parser.repairs.unshift({ offset: index, kind: 'ambiguous', reason: 'ambiguous-uri-boundary' });\n ambiguousScalarTail ||= parser.repairs.some((repair) => repair.reason === 'trailing-scalar-content');\n result.candidates.push({\n value: JSON.parse(json),\n json,\n start: index,\n end: parser.index,\n repairs: parser.repairs,\n requiresConfirmation: parser.repairs.some((repair) => repair.kind !== 'syntax'),\n });\n } catch (error) {\n if (result.errors.length < MAX_ERRORS)\n result.errors.push({ offset: parser.index, message: error instanceof Error ? error.message : String(error) });\n failures++;\n index = valueStart + 1;\n scalarBoundary = false;\n continue;\n }\n index = Math.max(index + 1, parser.index);\n scalarBoundary = true;\n }\n}\n\nfunction scalarStart(text: string, start: number, end: number): boolean {\n const first = text[start];\n if (first === undefined) return false;\n const keyword = /^([A-Za-z]+)/.exec(text.slice(start, end))?.[1];\n return (\n first in QUOTES ||\n /[-\\d]/.test(first) ||\n (keyword !== undefined &&\n (Object.hasOwn(KEYWORDS, keyword) ||\n (Object.keys(KEYWORDS).some((word) => word.startsWith(keyword)) &&\n /^[^\\S\\r\\n]*(?:[\\r\\n]|$)/.test(text.slice(start + keyword.length, end)))))\n );\n}\n\nclass RecoveryParser {\n readonly repairs: JsonRepair[] = [];\n readonly text: string;\n readonly end: number;\n index: number;\n\n constructor(text: string, index: number, end: number) {\n this.text = text;\n this.index = index;\n this.end = end;\n }\n\n finishScalar(regionEnd: number, start: number): boolean {\n const valueEnd = this.index;\n const atom = this.text.slice(start, valueEnd);\n const bullet = atom === '-' && /\\s/.test(this.text[valueEnd] ?? '');\n const retainLiteral =\n this.text[start]! in QUOTES || this.repairs.some((repair) => repair.reason === 'unquoted-value');\n this.space();\n if (bullet) return false;\n if (this.index >= regionEnd) return true;\n if (/[\\r\\n]/.test(this.text.slice(valueEnd, this.index))) {\n this.repair('ambiguous', 'scalar-before-prose', valueEnd);\n return true;\n }\n if (/^\\d+[.)]$/.test(atom) && /[ \\t]/.test(this.text[valueEnd] ?? '')) return false;\n if (retainLiteral || /^[\\p{P}\\p{S}]/u.test(this.text.slice(this.index, regionEnd))) {\n this.repair('ambiguous', 'trailing-scalar-content', valueEnd);\n return true;\n }\n return false;\n }\n\n value(depth: number): string {\n if (depth > MAX_DEPTH) throw new Error('JSON nesting exceeds 128 levels');\n this.space();\n const char = this.text[this.index];\n if (this.index >= this.end || char === ',' || char === '}' || char === ']') {\n this.repair('incomplete', 'missing-value');\n return 'null';\n }\n if (char === '{' || char === '[') {\n if (depth >= MAX_DEPTH) throw new Error('JSON nesting exceeds 128 levels');\n return this.container(depth, char === '{');\n }\n if (char !== undefined && char in QUOTES) return this.string(depth > 0 ? 'value' : 'root');\n const start = this.index;\n const uriEnd = unquotedUriEnd(this.text, start, this.end);\n if (uriEnd !== undefined) this.index = uriEnd;\n else\n while (\n this.index < this.end &&\n !/[\\s,}\\]]/.test(this.text[this.index]!) &&\n !(depth === 0 && /[{[]/.test(this.text[this.index]!)) &&\n !this.comment()\n )\n this.index++;\n if (this.index === start) throw new Error('Expected a JSON value');\n const token = this.text.slice(start, this.index);\n if (/^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$/.test(token)) return token;\n if (Object.hasOwn(KEYWORDS, token)) {\n const canonical = KEYWORDS[token]!;\n if (canonical !== token) this.repair('syntax', 'python-keyword', start);\n return canonical;\n }\n this.repair(this.index >= this.end ? 'incomplete' : 'ambiguous', 'unquoted-value', start);\n return JSON.stringify(token);\n }\n\n private container(depth: number, object: boolean): string {\n this.index++;\n const close = object ? '}' : ']';\n const items: string[] = [];\n const keys = new Set<string>();\n let afterComma = false;\n let commaOffset = this.index;\n for (;;) {\n this.space();\n if (this.index >= this.end || this.text[this.index] === close) {\n if (this.index >= this.end) this.repair('incomplete', `missing-${close}`);\n else this.index++;\n if (afterComma) this.repair('syntax', 'trailing-comma', commaOffset);\n return (object ? '{' : '[') + items.join(',') + close;\n }\n if (this.text[this.index] === '}' || this.text[this.index] === ']') throw new Error('Mismatched closing bracket');\n if (this.text[this.index] === ',') {\n if (object) this.repair('ambiguous', 'extra-comma');\n else {\n items.push('null');\n this.repair('incomplete', 'missing-value');\n }\n commaOffset = this.index;\n afterComma = true;\n this.index++;\n continue;\n }\n let key: string | undefined;\n if (object) {\n const start = this.index;\n if (this.text[this.index]! in QUOTES) key = this.string();\n else {\n while (this.index < this.end && !/[\\s:,{}[\\]]/.test(this.text[this.index]!) && !this.comment()) this.index++;\n if (this.index === start) throw new Error('Expected an object key');\n const rawKey = this.text.slice(start, this.index);\n key = JSON.stringify(rawKey);\n this.repair(/[\"'“”‘’]/.test(rawKey) ? 'ambiguous' : 'syntax', 'unquoted-key', start);\n }\n const decoded: string = JSON.parse(key);\n if (keys.has(decoded)) this.repair('ambiguous', 'duplicate-key', start);\n keys.add(decoded);\n this.space();\n if (this.text[this.index] === ':') this.index++;\n else this.repair('ambiguous', 'missing-colon');\n }\n const value = this.value(depth + 1);\n items.push(key === undefined ? value : `${key}:${value}`);\n this.space();\n afterComma = this.text[this.index] === ',';\n if (afterComma) {\n commaOffset = this.index;\n this.index++;\n } else if (this.index < this.end && this.text[this.index] !== close) this.repair('syntax', 'missing-comma');\n }\n }\n\n private string(context: 'root' | 'key' | 'value' = 'key'): string {\n const start = this.index;\n const open = this.text[this.index++]!;\n const close = QUOTES[open]!;\n if (open !== '\"') this.repair('syntax', 'non-json-quote', start);\n let value = '';\n let tail = '';\n const append = (text: string): void => {\n value += text;\n tail = (tail + text).slice(-2);\n };\n let embeddedQuote = false;\n const family = '\"“”'.includes(open) ? '\"“”' : \"'‘’\";\n let alternative: { end: number; value: string; repairCount: number } | undefined;\n while (this.index < this.end) {\n const char = this.text[this.index++]!;\n if (\n \"'‘’\".includes(open) &&\n \"'’\".includes(char) &&\n /[\\p{L}\\p{N}]$/u.test(tail) &&\n /^[\\p{L}\\p{N}]/u.test(this.text.slice(this.index, this.end))\n ) {\n this.repair('ambiguous', 'literal-apostrophe', this.index - 1);\n append(char);\n continue;\n }\n if (family.includes(char)) {\n const after = this.text.slice(this.index, this.end).trimStart()[0];\n const delimited = after === undefined || /[,}\\]:\"']/.test(after);\n if (char === close) {\n if (embeddedQuote) {\n embeddedQuote = false;\n this.repair('ambiguous', 'unescaped-quote', this.index - 1);\n append(char);\n continue;\n }\n if (context !== 'root' && alternative !== undefined && !delimited) {\n this.index = alternative.end;\n this.repairs.length = alternative.repairCount;\n this.repair('ambiguous', 'mismatched-quote', this.index - 1);\n return JSON.stringify(alternative.value);\n }\n const nextClose = this.text.indexOf(close, this.index);\n const afterNext = this.text.slice(nextClose + 1, this.end).trimStart()[0];\n if (\n context === 'value' &&\n !delimited &&\n !/\\s/.test(this.text[this.index] ?? '') &&\n nextClose > this.index &&\n nextClose < this.end &&\n afterNext !== undefined &&\n (!/[,}:\\]]/.test(afterNext) ||\n (afterNext === ',' && this.continuesStringAfterComma(nextClose + 1, close))) &&\n !/[\\\\*:,{}[\\]\\r\\n]|\\/\\//.test(this.text.slice(this.index, nextClose)) &&\n !this.startsKey(nextClose)\n ) {\n embeddedQuote = true;\n this.repair('ambiguous', 'unescaped-quote', this.index - 1);\n append(char);\n continue;\n }\n return JSON.stringify(value);\n }\n if (delimited) alternative ??= { end: this.index, value, repairCount: this.repairs.length };\n }\n if (char !== '\\\\') {\n if (char.codePointAt(0)! < 32) this.repair('syntax', 'unescaped-control-character', this.index - 1);\n append(char);\n continue;\n }\n const escapeOffset = this.index - 1;\n if (this.index >= this.end) {\n append('\\\\');\n this.repair('incomplete', 'truncated-escape', escapeOffset);\n break;\n }\n const escape = this.text[this.index++]!;\n if (escape === 'u') {\n const hex = this.text.slice(this.index, Math.min(this.index + 4, this.end));\n if (/^[\\da-fA-F]{4}$/.test(hex)) {\n append(String.fromCodePoint(Number.parseInt(hex, 16)));\n this.index += 4;\n } else {\n append(String.raw`\\u`);\n this.repair(\n /^[\\da-fA-F]{0,3}$/.test(hex) ? 'incomplete' : 'ambiguous',\n 'invalid-unicode-escape',\n escapeOffset\n );\n }\n } else if (String.raw`\"\\/bfnrt`.includes(escape)) {\n append(JSON.parse(`\"\\\\${escape}\"`) as string);\n } else if (escape === \"'\" && open === \"'\") append(\"'\");\n else {\n append(`\\\\${escape}`);\n this.repair('ambiguous', 'invalid-escape', escapeOffset);\n }\n }\n this.repair('incomplete', 'unterminated-string', start);\n return JSON.stringify(value);\n }\n\n private continuesStringAfterComma(start: number, quote: string): boolean {\n const parser = new RecoveryParser(this.text, start - 1, this.end);\n parser.string();\n const end = parser.index - 1;\n if (\n this.text[end] !== quote ||\n parser.repairs.some(\n (repair) => !['non-json-quote', 'literal-apostrophe', 'unescaped-control-character'].includes(repair.reason)\n )\n )\n return false;\n const continuation = this.text.slice(start, end);\n const after = this.text.slice(end + 1, this.end).trimStart()[0];\n return (\n /^\\s*,\\s*[\\p{L}\\p{N}]/u.test(continuation) &&\n !/[\\\\:{}[\\]]/.test(continuation) &&\n (after === undefined || /[,}\\]]/.test(after))\n );\n }\n\n private startsKey(index: number): boolean {\n const parser = new RecoveryParser(this.text, index, this.end);\n parser.string();\n parser.space();\n return this.text[parser.index] === ':';\n }\n\n space(): void {\n while (this.index < this.end) {\n if (/\\s/.test(this.text[this.index]!)) {\n if (!/[ \\t\\r\\n]/.test(this.text[this.index]!)) this.repair('syntax', 'non-json-whitespace');\n this.index++;\n } else if (this.text.startsWith('//', this.index)) {\n this.repair('syntax', 'line-comment');\n while (this.index < this.end && !/[\\r\\n]/.test(this.text[this.index]!)) this.index++;\n } else if (this.text.startsWith('/*', this.index)) {\n const end = this.text.indexOf('*/', this.index + 2);\n this.repair(end === -1 || end >= this.end ? 'incomplete' : 'syntax', 'block-comment');\n this.index = end === -1 || end >= this.end ? this.end : end + 2;\n } else break;\n }\n }\n\n private repair(kind: JsonRepair['kind'], reason: string, offset = this.index): void {\n this.repairs.push({ offset, kind, reason });\n }\n\n private comment(): boolean {\n return this.text.startsWith('//', this.index) || this.text.startsWith('/*', this.index);\n }\n}\n\nfunction unquotedUriEnd(text: string, start: number, end: number): number | undefined {\n const match = /^[A-Za-z][A-Za-z\\d+.-]*:\\/\\//.exec(text.slice(start, end));\n if (match === null) return;\n let index = start + match[0].length;\n let brackets = 0;\n while (index < end && !/[\\s}]/.test(text[index]!)) {\n if (text[index] === ',' && brackets === 0) break;\n if (text[index] === '[') brackets++;\n else if (text[index] === ']') {\n if (brackets === 0) break;\n brackets--;\n }\n index++;\n }\n return index;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"recoverJson.js","names":[],"sources":["../src/recoverJson.ts"],"sourcesContent":["/*! JSON recovery informed by jsonrepair, Copyright (c) 2020-2026 Jos de Jong (ISC). See NOTICE. */\n\nimport { getErrorMessage } from './error.js';\n\nexport interface JsonRepair {\n /** UTF-16 offset in the original response. */\n offset: number;\n kind: 'syntax' | 'incomplete' | 'ambiguous';\n reason: string;\n}\n\nexport interface RecoveredJson {\n value: unknown;\n json: string;\n start: number;\n end: number;\n repairs: JsonRepair[];\n /** Missing content or an ambiguous interpretation requires confirmation before acting on this value. */\n requiresConfirmation: boolean;\n}\n\nexport interface JsonRecovery {\n candidates: RecoveredJson[];\n errors: { offset: number; message: string }[];\n}\n\nconst MAX_INPUT_LENGTH = 1_000_000;\nconst MAX_DEPTH = 128;\nconst MAX_CANDIDATES = 32;\nconst MAX_ERRORS = 32;\nconst MAX_DIAGNOSTIC_EXCERPT = 256;\nconst QUOTES: Record<string, string> = { '\"': '\"', \"'\": \"'\", '“': '”', '”': '”', '‘': '’', '’': '’' };\nconst KEYWORDS: Record<string, string> = {\n true: 'true',\n false: 'false',\n null: 'null',\n True: 'true',\n False: 'false',\n None: 'null',\n};\n\n/**\n * Extracts JSON values from a response, repairing common LLM syntax and retaining repair provenance.\n * Offsets refer to the original string. All candidates are returned: choosing among multiple answers,\n * schema validation, and provider truncation signals belong to the caller. No schema values are coerced.\n * Bounded to one million UTF-16 code units, 128 nesting levels, and 32 candidates/errors each.\n * A region is abandoned after 32 failed starts; later Markdown regions can still yield candidates.\n */\nexport function recoverJson(text: string): JsonRecovery {\n const result: JsonRecovery = { candidates: [], errors: [] };\n if (text.length > MAX_INPUT_LENGTH) {\n result.errors.push({ offset: MAX_INPUT_LENGTH, message: 'JSON recovery input exceeds one million characters' });\n return result;\n }\n const fences = [...text.matchAll(/^(?: {0,3})(`{3,}|~{3,})[^\\r\\n]*(?:\\r\\n|[\\r\\n]|$)/gm)].flatMap((fence) => {\n const marker = fence[1]!;\n const markerEnd = fence.index + fence[0].indexOf(marker) + marker.length;\n const lineEnd = fence.index + fence[0].length;\n const info = text.slice(markerEnd, lineEnd);\n const inlinePrefix = /^[ \\t]*json(?=[ \\t{[\"'“”‘’])[ \\t]*/i.exec(info);\n const inlineStart = inlinePrefix === null ? lineEnd : markerEnd + inlinePrefix[0].length;\n const start =\n text[inlineStart] === '{' || text[inlineStart] === '[' || scalarStart(text, inlineStart, lineEnd)\n ? inlineStart\n : lineEnd;\n return marker[0] === '`' && start === lineEnd && info.includes('`') ? [] : [{ index: fence.index, marker, start }];\n });\n if (fences.length > 0) {\n let consumed = 0;\n for (const fence of fences) {\n if (fence.index < consumed) continue;\n extractRegion(text, consumed, fence.index, result);\n const parsedThrough = result.candidates.at(-1)?.end ?? consumed;\n if (parsedThrough > fence.index) {\n consumed = parsedThrough;\n continue;\n }\n const { marker, start } = fence;\n const close = new RegExp(`^ {0,3}${marker[0]}{${marker.length},}[ \\\\t]*$`, 'gm');\n close.lastIndex = start;\n const match = close.exec(text);\n const end = match?.index ?? text.length;\n extractRegion(text, start, end, result);\n const extendedEnd = result.candidates.at(-1)?.end ?? start;\n if (extendedEnd > end) {\n close.lastIndex = extendedEnd;\n const outerClose = close.exec(text);\n if (outerClose !== null && !fences.some((next) => next.index >= extendedEnd && next.index < outerClose.index)) {\n extractRegion(text, extendedEnd, outerClose.index, result);\n consumed = outerClose.index + outerClose[0].length;\n continue;\n }\n }\n consumed = Math.max(\n result.candidates.at(-1)?.end ?? start,\n match === null ? text.length : match.index + match[0].length\n );\n }\n extractRegion(text, consumed, text.length, result);\n } else {\n extractRegion(text, 0, text.length, result);\n }\n if (result.candidates.length === MAX_CANDIDATES) {\n const error = {\n offset: result.candidates.at(-1)!.end,\n message: 'JSON candidate limit reached; extraction may be incomplete',\n };\n if (result.errors.length === MAX_ERRORS) result.errors[MAX_ERRORS - 1] = error;\n else result.errors.push(error);\n }\n return result;\n}\n\nfunction extractRegion(text: string, start: number, end: number, result: JsonRecovery, commentFragment = false): void {\n if (result.candidates.length >= MAX_CANDIDATES) return;\n let index = start;\n let failures = 0;\n let ambiguousScalarTail = false;\n let scalarBoundary = true;\n let uriBoundaryEnd = start;\n let uriTokenEnd = start;\n let uriContainerStart = start;\n while (index < end && /\\s/.test(text[index]!)) index++;\n const firstIndex = index;\n const initialParser = new RecoveryParser(text, index, end);\n if (!commentFragment) initialParser.space();\n const initialValueStart = initialParser.index;\n if (initialValueStart >= end) {\n if (initialParser.repairs.some((repair) => repair.kind === 'incomplete') && result.errors.length < MAX_ERRORS)\n result.errors.push({ offset: index, message: 'Incomplete leading JSON comment' });\n return;\n }\n const first = text[initialValueStart];\n // Within prose, scalar starts need a line boundary; containers may appear inline.\n const rootValue = scalarStart(text, initialValueStart, end);\n const initialValue = rootValue || first === '{' || first === '[';\n if (!initialValue) index = initialValueStart;\n while (index < end && result.candidates.length < MAX_CANDIDATES && failures < MAX_ERRORS) {\n if (!initialValue || index !== firstIndex) {\n while (index < end && text[index] !== '{' && text[index] !== '[') {\n if (scalarBoundary && scalarStart(text, index, end)) break;\n const uriEnd =\n index === start || !/[\\w+.-]/.test(text[index - 1]!) ? unquotedUriEnd(text, index, end) : undefined;\n if (uriEnd !== undefined) {\n if (index >= uriTokenEnd) {\n const whitespace = text.slice(index, end).search(/\\s/);\n uriTokenEnd = whitespace === -1 ? end : index + whitespace;\n uriContainerStart = index;\n }\n if (index >= uriContainerStart) {\n const container = text.slice(index, uriTokenEnd).search(/[{[]/);\n uriContainerStart = container === -1 ? uriTokenEnd : index + container;\n }\n if (uriContainerStart < uriTokenEnd) uriBoundaryEnd = Math.max(uriBoundaryEnd, uriTokenEnd);\n index = Math.min(uriEnd, uriContainerStart);\n scalarBoundary = false;\n continue;\n }\n if (!commentFragment && text[index] === '/') {\n const trivia = new RecoveryParser(text, index, end);\n trivia.space();\n if (trivia.index > index) {\n if (trivia.repairs.some((repair) => repair.kind === 'incomplete') && result.errors.length < MAX_ERRORS)\n result.errors.push({ offset: index, message: 'Possibly unterminated comment-like span in prose' });\n extractRegion(text, index + 2, trivia.index, result, true);\n scalarBoundary ||= /[\\r\\n]/.test(text.slice(index, trivia.index));\n index = trivia.index;\n continue;\n }\n }\n if (/[\\r\\n]/.test(text[index]!)) scalarBoundary = true;\n else if (!/[\\s,]/.test(text[index]!)) scalarBoundary = false;\n index++;\n }\n }\n if (index >= end || result.candidates.length >= MAX_CANDIDATES) break;\n let parser = initialValue && index === firstIndex ? initialParser : new RecoveryParser(text, index, end);\n const valueStart = parser.index;\n try {\n let json = parser.value(0);\n if (\n !commentFragment &&\n (text[valueStart] === '{' || text[valueStart] === '[') &&\n parser.index === end &&\n end < text.length\n ) {\n const extended = new RecoveryParser(text, index, text.length);\n try {\n const extendedJson = extended.value(0);\n if (\n extended.index > end &&\n extended.repairs.every((repair) => repair.reason === 'unescaped-control-character')\n ) {\n extended.repairs.push({ offset: end, kind: 'ambiguous', reason: 'literal-fence-in-string' });\n parser = extended;\n json = extendedJson;\n }\n } catch {\n // Keep the bounded interpretation when extending it is not a complete JSON document.\n }\n }\n const valueEnd = parser.index;\n if (text[valueStart] !== '{' && text[valueStart] !== '[' && !parser.finishScalar(end, valueStart)) {\n scalarBoundary = false;\n index = valueEnd;\n continue;\n }\n parser.space();\n if (!commentFragment && failures === 0 && parser.index < end && /[}\\]]/.test(text[parser.index]!)) {\n const surplusStart = parser.index;\n while (parser.index < end && /[}\\]]/.test(text[parser.index]!)) {\n parser.repairs.push({ offset: parser.index, kind: 'ambiguous', reason: 'surplus-closing-bracket' });\n parser.index++;\n parser.space();\n }\n if (result.errors.length < MAX_ERRORS) {\n const excerptEnd = Math.min(end, surplusStart + MAX_DIAGNOSTIC_EXCERPT);\n result.errors.push({\n offset: surplusStart,\n message: `Surplus closing brackets and possible continuation (${excerptEnd < end ? 'truncated excerpt' : 'excerpt'}): ${JSON.stringify(text.slice(surplusStart, excerptEnd))}`,\n });\n }\n }\n if (\n text[valueStart]! in QUOTES &&\n parser.repairs.some((repair) => repair.reason === 'trailing-scalar-content') &&\n result.errors.length < MAX_ERRORS\n ) {\n const excerptEnd = Math.min(end, valueEnd + MAX_DIAGNOSTIC_EXCERPT);\n result.errors.push({\n offset: valueEnd,\n message: `Ambiguous quoted-scalar tail (${excerptEnd < end ? 'truncated excerpt' : 'excerpt'}): ${JSON.stringify(text.slice(valueEnd, excerptEnd))}`,\n });\n }\n if (commentFragment)\n parser.repairs.unshift({ offset: index, kind: 'ambiguous', reason: 'fragment-in-comment-like-prose' });\n if (failures > 0)\n parser.repairs.unshift({ offset: index, kind: 'ambiguous', reason: 'fragment-after-rejected-document' });\n if (ambiguousScalarTail)\n parser.repairs.unshift({ offset: index, kind: 'ambiguous', reason: 'fragment-after-ambiguous-scalar' });\n if (index < uriBoundaryEnd)\n parser.repairs.unshift({ offset: index, kind: 'ambiguous', reason: 'ambiguous-uri-boundary' });\n ambiguousScalarTail ||= parser.repairs.some((repair) => repair.reason === 'trailing-scalar-content');\n result.candidates.push({\n value: JSON.parse(json),\n json,\n start: index,\n end: parser.index,\n repairs: parser.repairs,\n requiresConfirmation: parser.repairs.some((repair) => repair.kind !== 'syntax'),\n });\n } catch (error) {\n if (result.errors.length < MAX_ERRORS)\n result.errors.push({ offset: parser.index, message: getErrorMessage(error) });\n failures++;\n index = valueStart + 1;\n scalarBoundary = false;\n continue;\n }\n index = Math.max(index + 1, parser.index);\n scalarBoundary = true;\n }\n}\n\nfunction scalarStart(text: string, start: number, end: number): boolean {\n const first = text[start];\n if (first === undefined) return false;\n const keyword = /^([A-Za-z]+)/.exec(text.slice(start, end))?.[1];\n return (\n first in QUOTES ||\n /[-\\d]/.test(first) ||\n (keyword !== undefined &&\n (Object.hasOwn(KEYWORDS, keyword) ||\n (Object.keys(KEYWORDS).some((word) => word.startsWith(keyword)) &&\n /^[^\\S\\r\\n]*(?:[\\r\\n]|$)/.test(text.slice(start + keyword.length, end)))))\n );\n}\n\nclass RecoveryParser {\n readonly repairs: JsonRepair[] = [];\n readonly text: string;\n readonly end: number;\n index: number;\n\n constructor(text: string, index: number, end: number) {\n this.text = text;\n this.index = index;\n this.end = end;\n }\n\n finishScalar(regionEnd: number, start: number): boolean {\n const valueEnd = this.index;\n const atom = this.text.slice(start, valueEnd);\n const bullet = atom === '-' && /\\s/.test(this.text[valueEnd] ?? '');\n const retainLiteral =\n this.text[start]! in QUOTES || this.repairs.some((repair) => repair.reason === 'unquoted-value');\n this.space();\n if (bullet) return false;\n if (this.index >= regionEnd) return true;\n if (/[\\r\\n]/.test(this.text.slice(valueEnd, this.index))) {\n this.repair('ambiguous', 'scalar-before-prose', valueEnd);\n return true;\n }\n if (/^\\d+[.)]$/.test(atom) && /[ \\t]/.test(this.text[valueEnd] ?? '')) return false;\n if (retainLiteral || /^[\\p{P}\\p{S}]/u.test(this.text.slice(this.index, regionEnd))) {\n this.repair('ambiguous', 'trailing-scalar-content', valueEnd);\n return true;\n }\n return false;\n }\n\n value(depth: number): string {\n if (depth > MAX_DEPTH) throw new Error('JSON nesting exceeds 128 levels');\n this.space();\n const char = this.text[this.index];\n if (this.index >= this.end || char === ',' || char === '}' || char === ']') {\n this.repair('incomplete', 'missing-value');\n return 'null';\n }\n if (char === '{' || char === '[') {\n if (depth >= MAX_DEPTH) throw new Error('JSON nesting exceeds 128 levels');\n return this.container(depth, char === '{');\n }\n if (char !== undefined && char in QUOTES) return this.string(depth > 0 ? 'value' : 'root');\n const start = this.index;\n const uriEnd = unquotedUriEnd(this.text, start, this.end);\n if (uriEnd !== undefined) this.index = uriEnd;\n else\n while (\n this.index < this.end &&\n !/[\\s,}\\]]/.test(this.text[this.index]!) &&\n !(depth === 0 && /[{[]/.test(this.text[this.index]!)) &&\n !this.comment()\n )\n this.index++;\n if (this.index === start) throw new Error('Expected a JSON value');\n const token = this.text.slice(start, this.index);\n if (/^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$/.test(token)) return token;\n if (Object.hasOwn(KEYWORDS, token)) {\n const canonical = KEYWORDS[token]!;\n if (canonical !== token) this.repair('syntax', 'python-keyword', start);\n return canonical;\n }\n this.repair(this.index >= this.end ? 'incomplete' : 'ambiguous', 'unquoted-value', start);\n return JSON.stringify(token);\n }\n\n private container(depth: number, object: boolean): string {\n this.index++;\n const close = object ? '}' : ']';\n const items: string[] = [];\n const keys = new Set<string>();\n let afterComma = false;\n let commaOffset = this.index;\n for (;;) {\n this.space();\n if (this.index >= this.end || this.text[this.index] === close) {\n if (this.index >= this.end) this.repair('incomplete', `missing-${close}`);\n else this.index++;\n if (afterComma) this.repair('syntax', 'trailing-comma', commaOffset);\n return (object ? '{' : '[') + items.join(',') + close;\n }\n if (this.text[this.index] === '}' || this.text[this.index] === ']') throw new Error('Mismatched closing bracket');\n if (this.text[this.index] === ',') {\n if (object) this.repair('ambiguous', 'extra-comma');\n else {\n items.push('null');\n this.repair('incomplete', 'missing-value');\n }\n commaOffset = this.index;\n afterComma = true;\n this.index++;\n continue;\n }\n let key: string | undefined;\n if (object) {\n const start = this.index;\n if (this.text[this.index]! in QUOTES) key = this.string();\n else {\n while (this.index < this.end && !/[\\s:,{}[\\]]/.test(this.text[this.index]!) && !this.comment()) this.index++;\n if (this.index === start) throw new Error('Expected an object key');\n const rawKey = this.text.slice(start, this.index);\n key = JSON.stringify(rawKey);\n this.repair(/[\"'“”‘’]/.test(rawKey) ? 'ambiguous' : 'syntax', 'unquoted-key', start);\n }\n const decoded: string = JSON.parse(key);\n if (keys.has(decoded)) this.repair('ambiguous', 'duplicate-key', start);\n keys.add(decoded);\n this.space();\n if (this.text[this.index] === ':') this.index++;\n else this.repair('ambiguous', 'missing-colon');\n }\n const value = this.value(depth + 1);\n items.push(key === undefined ? value : `${key}:${value}`);\n this.space();\n afterComma = this.text[this.index] === ',';\n if (afterComma) {\n commaOffset = this.index;\n this.index++;\n } else if (this.index < this.end && this.text[this.index] !== close) this.repair('syntax', 'missing-comma');\n }\n }\n\n private string(context: 'root' | 'key' | 'value' = 'key'): string {\n const start = this.index;\n const open = this.text[this.index++]!;\n const close = QUOTES[open]!;\n if (open !== '\"') this.repair('syntax', 'non-json-quote', start);\n let value = '';\n let tail = '';\n const append = (text: string): void => {\n value += text;\n tail = (tail + text).slice(-2);\n };\n let embeddedQuote = false;\n const family = '\"“”'.includes(open) ? '\"“”' : \"'‘’\";\n let alternative: { end: number; value: string; repairCount: number } | undefined;\n while (this.index < this.end) {\n const char = this.text[this.index++]!;\n if (\n \"'‘’\".includes(open) &&\n \"'’\".includes(char) &&\n /[\\p{L}\\p{N}]$/u.test(tail) &&\n /^[\\p{L}\\p{N}]/u.test(this.text.slice(this.index, this.end))\n ) {\n this.repair('ambiguous', 'literal-apostrophe', this.index - 1);\n append(char);\n continue;\n }\n if (family.includes(char)) {\n const after = this.text.slice(this.index, this.end).trimStart()[0];\n const delimited = after === undefined || /[,}\\]:\"']/.test(after);\n if (char === close) {\n if (embeddedQuote) {\n embeddedQuote = false;\n this.repair('ambiguous', 'unescaped-quote', this.index - 1);\n append(char);\n continue;\n }\n if (context !== 'root' && alternative !== undefined && !delimited) {\n this.index = alternative.end;\n this.repairs.length = alternative.repairCount;\n this.repair('ambiguous', 'mismatched-quote', this.index - 1);\n return JSON.stringify(alternative.value);\n }\n const nextClose = this.text.indexOf(close, this.index);\n const afterNext = this.text.slice(nextClose + 1, this.end).trimStart()[0];\n if (\n context === 'value' &&\n !delimited &&\n !/\\s/.test(this.text[this.index] ?? '') &&\n nextClose > this.index &&\n nextClose < this.end &&\n afterNext !== undefined &&\n (!/[,}:\\]]/.test(afterNext) ||\n (afterNext === ',' && this.continuesStringAfterComma(nextClose + 1, close))) &&\n !/[\\\\*:,{}[\\]\\r\\n]|\\/\\//.test(this.text.slice(this.index, nextClose)) &&\n !this.startsKey(nextClose)\n ) {\n embeddedQuote = true;\n this.repair('ambiguous', 'unescaped-quote', this.index - 1);\n append(char);\n continue;\n }\n return JSON.stringify(value);\n }\n if (delimited) alternative ??= { end: this.index, value, repairCount: this.repairs.length };\n }\n if (char !== '\\\\') {\n if (char.codePointAt(0)! < 32) this.repair('syntax', 'unescaped-control-character', this.index - 1);\n append(char);\n continue;\n }\n const escapeOffset = this.index - 1;\n if (this.index >= this.end) {\n append('\\\\');\n this.repair('incomplete', 'truncated-escape', escapeOffset);\n break;\n }\n const escape = this.text[this.index++]!;\n if (escape === 'u') {\n const hex = this.text.slice(this.index, Math.min(this.index + 4, this.end));\n if (/^[\\da-fA-F]{4}$/.test(hex)) {\n append(String.fromCodePoint(Number.parseInt(hex, 16)));\n this.index += 4;\n } else {\n append(String.raw`\\u`);\n this.repair(\n /^[\\da-fA-F]{0,3}$/.test(hex) ? 'incomplete' : 'ambiguous',\n 'invalid-unicode-escape',\n escapeOffset\n );\n }\n } else if (String.raw`\"\\/bfnrt`.includes(escape)) {\n append(JSON.parse(`\"\\\\${escape}\"`) as string);\n } else if (escape === \"'\" && open === \"'\") append(\"'\");\n else {\n append(`\\\\${escape}`);\n this.repair('ambiguous', 'invalid-escape', escapeOffset);\n }\n }\n this.repair('incomplete', 'unterminated-string', start);\n return JSON.stringify(value);\n }\n\n private continuesStringAfterComma(start: number, quote: string): boolean {\n const parser = new RecoveryParser(this.text, start - 1, this.end);\n parser.string();\n const end = parser.index - 1;\n if (\n this.text[end] !== quote ||\n parser.repairs.some(\n (repair) => !['non-json-quote', 'literal-apostrophe', 'unescaped-control-character'].includes(repair.reason)\n )\n )\n return false;\n const continuation = this.text.slice(start, end);\n const after = this.text.slice(end + 1, this.end).trimStart()[0];\n return (\n /^\\s*,\\s*[\\p{L}\\p{N}]/u.test(continuation) &&\n !/[\\\\:{}[\\]]/.test(continuation) &&\n (after === undefined || /[,}\\]]/.test(after))\n );\n }\n\n private startsKey(index: number): boolean {\n const parser = new RecoveryParser(this.text, index, this.end);\n parser.string();\n parser.space();\n return this.text[parser.index] === ':';\n }\n\n space(): void {\n while (this.index < this.end) {\n if (/\\s/.test(this.text[this.index]!)) {\n if (!/[ \\t\\r\\n]/.test(this.text[this.index]!)) this.repair('syntax', 'non-json-whitespace');\n this.index++;\n } else if (this.text.startsWith('//', this.index)) {\n this.repair('syntax', 'line-comment');\n while (this.index < this.end && !/[\\r\\n]/.test(this.text[this.index]!)) this.index++;\n } else if (this.text.startsWith('/*', this.index)) {\n const end = this.text.indexOf('*/', this.index + 2);\n this.repair(end === -1 || end >= this.end ? 'incomplete' : 'syntax', 'block-comment');\n this.index = end === -1 || end >= this.end ? this.end : end + 2;\n } else break;\n }\n }\n\n private repair(kind: JsonRepair['kind'], reason: string, offset = this.index): void {\n this.repairs.push({ offset, kind, reason });\n }\n\n private comment(): boolean {\n return this.text.startsWith('//', this.index) || this.text.startsWith('/*', this.index);\n }\n}\n\nfunction unquotedUriEnd(text: string, start: number, end: number): number | undefined {\n const match = /^[A-Za-z][A-Za-z\\d+.-]*:\\/\\//.exec(text.slice(start, end));\n if (match === null) return;\n let index = start + match[0].length;\n let brackets = 0;\n while (index < end && !/[\\s}]/.test(text[index]!)) {\n if (text[index] === ',' && brackets === 0) break;\n if (text[index] === '[') brackets++;\n else if (text[index] === ']') {\n if (brackets === 0) break;\n brackets--;\n }\n index++;\n }\n return index;\n}\n"],"mappings":"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"}
package/dist/sqlite.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";function e(){return`PRAGMA foreign_keys = ON; PRAGMA busy_timeout = 5000; PRAGMA cache_size = -16000; PRAGMA synchronous = NORMAL; PRAGMA wal_autocheckpoint = 10000;`}function t(){return`PRAGMA journal_mode = WAL;`}exports.getConnectionLevelSqlitePragmas=e,exports.getPersistentSqlitePragmas=t;
1
+ "use strict";function e(){return`PRAGMA foreign_keys = ON; PRAGMA busy_timeout = 5000; PRAGMA cache_size = -16000; PRAGMA synchronous = NORMAL; PRAGMA wal_autocheckpoint = 10000;`}function t(){return`PRAGMA journal_mode = WAL;`}function n(e){return e.replaceAll(/[%\\_]/gu,String.raw`\$&`)}exports.escapeLikePattern=n,exports.getConnectionLevelSqlitePragmas=e,exports.getPersistentSqlitePragmas=t;
2
2
  //# sourceMappingURL=sqlite.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite.cjs","names":[],"sources":["../src/sqlite.ts"],"sourcesContent":["export function getConnectionLevelSqlitePragmas(): string {\n // cf. https://github.com/benbjohnson/litestream/issues/724#issue-3367254318\n // cf. https://github.com/benbjohnson/litestream/blob/9bd72348b7e7b1b3b8cf1e8befbee3b2c17444f7/.claude/agents/performance-optimizer.md?plain=1#L225-L232\n return 'PRAGMA foreign_keys = ON; PRAGMA busy_timeout = 5000; PRAGMA cache_size = -16000; PRAGMA synchronous = NORMAL; PRAGMA wal_autocheckpoint = 10000;';\n}\n\nexport function getPersistentSqlitePragmas(): string {\n return 'PRAGMA journal_mode = WAL;';\n}\n"],"mappings":"aAAA,SAAgB,GAA0C,CAGxD,MAAO,mJACT,CAEA,SAAgB,GAAqC,CACnD,MAAO,4BACT"}
1
+ {"version":3,"file":"sqlite.cjs","names":[],"sources":["../src/sqlite.ts"],"sourcesContent":["export function getConnectionLevelSqlitePragmas(): string {\n // cf. https://github.com/benbjohnson/litestream/issues/724#issue-3367254318\n // cf. https://github.com/benbjohnson/litestream/blob/9bd72348b7e7b1b3b8cf1e8befbee3b2c17444f7/.claude/agents/performance-optimizer.md?plain=1#L225-L232\n return 'PRAGMA foreign_keys = ON; PRAGMA busy_timeout = 5000; PRAGMA cache_size = -16000; PRAGMA synchronous = NORMAL; PRAGMA wal_autocheckpoint = 10000;';\n}\n\nexport function getPersistentSqlitePragmas(): string {\n return 'PRAGMA journal_mode = WAL;';\n}\n\n/**\n * Escapes `%`, `_`, and `\\` so that `LIKE` does not read them as wildcards or escapes. SQLite's `LIKE` still matches\n * ASCII letters case-insensitively unless `PRAGMA case_sensitive_like = ON`; use `=` when case must match exactly.\n * The query must declare the escape character, e.g. `WHERE name LIKE ? ESCAPE '\\'` in SQL, which is `ESCAPE '\\\\'`\n * inside a JavaScript string literal.\n */\nexport function escapeLikePattern(text: string): string {\n return text.replaceAll(/[%\\\\_]/gu, String.raw`\\$&`);\n}\n"],"mappings":"aAAA,SAAgB,GAA0C,CAGxD,MAAO,mJACT,CAEA,SAAgB,GAAqC,CACnD,MAAO,4BACT,CAQA,SAAgB,EAAkB,EAAsB,CACtD,OAAO,EAAK,WAAW,WAAY,OAAO,GAAG,KAAK,CACpD"}
package/dist/sqlite.d.ts CHANGED
@@ -1,2 +1,9 @@
1
1
  export declare function getConnectionLevelSqlitePragmas(): string;
2
2
  export declare function getPersistentSqlitePragmas(): string;
3
+ /**
4
+ * Escapes `%`, `_`, and `\` so that `LIKE` does not read them as wildcards or escapes. SQLite's `LIKE` still matches
5
+ * ASCII letters case-insensitively unless `PRAGMA case_sensitive_like = ON`; use `=` when case must match exactly.
6
+ * The query must declare the escape character, e.g. `WHERE name LIKE ? ESCAPE '\'` in SQL, which is `ESCAPE '\\'`
7
+ * inside a JavaScript string literal.
8
+ */
9
+ export declare function escapeLikePattern(text: string): string;
package/dist/sqlite.js CHANGED
@@ -1,2 +1,2 @@
1
- function e(){return`PRAGMA foreign_keys = ON; PRAGMA busy_timeout = 5000; PRAGMA cache_size = -16000; PRAGMA synchronous = NORMAL; PRAGMA wal_autocheckpoint = 10000;`}function t(){return`PRAGMA journal_mode = WAL;`}export{e as getConnectionLevelSqlitePragmas,t as getPersistentSqlitePragmas};
1
+ function e(){return`PRAGMA foreign_keys = ON; PRAGMA busy_timeout = 5000; PRAGMA cache_size = -16000; PRAGMA synchronous = NORMAL; PRAGMA wal_autocheckpoint = 10000;`}function t(){return`PRAGMA journal_mode = WAL;`}function n(e){return e.replaceAll(/[%\\_]/gu,String.raw`\$&`)}export{n as escapeLikePattern,e as getConnectionLevelSqlitePragmas,t as getPersistentSqlitePragmas};
2
2
  //# sourceMappingURL=sqlite.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite.js","names":[],"sources":["../src/sqlite.ts"],"sourcesContent":["export function getConnectionLevelSqlitePragmas(): string {\n // cf. https://github.com/benbjohnson/litestream/issues/724#issue-3367254318\n // cf. https://github.com/benbjohnson/litestream/blob/9bd72348b7e7b1b3b8cf1e8befbee3b2c17444f7/.claude/agents/performance-optimizer.md?plain=1#L225-L232\n return 'PRAGMA foreign_keys = ON; PRAGMA busy_timeout = 5000; PRAGMA cache_size = -16000; PRAGMA synchronous = NORMAL; PRAGMA wal_autocheckpoint = 10000;';\n}\n\nexport function getPersistentSqlitePragmas(): string {\n return 'PRAGMA journal_mode = WAL;';\n}\n"],"mappings":"AAAA,SAAgB,GAA0C,CAGxD,MAAO,mJACT,CAEA,SAAgB,GAAqC,CACnD,MAAO,4BACT"}
1
+ {"version":3,"file":"sqlite.js","names":[],"sources":["../src/sqlite.ts"],"sourcesContent":["export function getConnectionLevelSqlitePragmas(): string {\n // cf. https://github.com/benbjohnson/litestream/issues/724#issue-3367254318\n // cf. https://github.com/benbjohnson/litestream/blob/9bd72348b7e7b1b3b8cf1e8befbee3b2c17444f7/.claude/agents/performance-optimizer.md?plain=1#L225-L232\n return 'PRAGMA foreign_keys = ON; PRAGMA busy_timeout = 5000; PRAGMA cache_size = -16000; PRAGMA synchronous = NORMAL; PRAGMA wal_autocheckpoint = 10000;';\n}\n\nexport function getPersistentSqlitePragmas(): string {\n return 'PRAGMA journal_mode = WAL;';\n}\n\n/**\n * Escapes `%`, `_`, and `\\` so that `LIKE` does not read them as wildcards or escapes. SQLite's `LIKE` still matches\n * ASCII letters case-insensitively unless `PRAGMA case_sensitive_like = ON`; use `=` when case must match exactly.\n * The query must declare the escape character, e.g. `WHERE name LIKE ? ESCAPE '\\'` in SQL, which is `ESCAPE '\\\\'`\n * inside a JavaScript string literal.\n */\nexport function escapeLikePattern(text: string): string {\n return text.replaceAll(/[%\\\\_]/gu, String.raw`\\$&`);\n}\n"],"mappings":"AAAA,SAAgB,GAA0C,CAGxD,MAAO,mJACT,CAEA,SAAgB,GAAqC,CACnD,MAAO,4BACT,CAQA,SAAgB,EAAkB,EAAsB,CACtD,OAAO,EAAK,WAAW,WAAY,OAAO,GAAG,KAAK,CACpD"}
package/dist/text.cjs CHANGED
@@ -1,4 +1,4 @@
1
1
  "use strict";function e(e){return e.replaceAll(/[$()*+.?[\\\]^{|}]/gu,String.raw`\$&`)}function t(e){return/^[\w./-]+$/u.test(e)?e:`'${e.replaceAll(`'`,String.raw`'\''`)}'`}function n(e,t=``){return i(`~`,e,t)}function r(e,t=``){return i("`",e,t)}function i(e,t,n){let r=e.repeat(3),i=2,a=t.indexOf(r);for(;a!==-1;){let n=a+3;for(;t[n]===e;)n++;i=Math.max(i,n-a),a=t.indexOf(r,n)}let o=0;for(;n[o]===e;)o++;let s=e.repeat(i+1+o);return`${s}${n.slice(o)}\n${t}${t.endsWith(`
2
2
  `)?``:`
3
- `}${s}`}exports.escapeRegExp=e,exports.quoteForShell=t,exports.toCodeBlock=r,exports.toTildeCodeBlock=n;
3
+ `}${s}`}function a(e,t,n=`…`){if(e.length<=t)return e;if(t<n.length)throw RangeError(`maxLength (${t}) must be at least the ellipsis length (${n.length})`);return`${o(e,t-n.length)}${n}`}function o(e,t){let n=e.charCodeAt(t-1);return e.slice(0,n>=55296&&n<=56319?t-1:t)}const s={'"':`&quot;`,"&":`&amp;`,"'":`&#39;`,"<":`&lt;`,">":`&gt;`},c=/["&'<>]/gu;function l(e){return e.search(c)===-1?e:e.replaceAll(c,e=>s[e])}exports.escapeHtml=l,exports.escapeRegExp=e,exports.quoteForShell=t,exports.sliceWithoutSplittingSurrogates=o,exports.toCodeBlock=r,exports.toTildeCodeBlock=n,exports.truncate=a;
4
4
  //# sourceMappingURL=text.cjs.map
package/dist/text.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"text.cjs","names":[],"sources":["../src/text.ts"],"sourcesContent":["/** Escapes every RegExp metacharacter so the text matches itself literally. */\nexport function escapeRegExp(text: string): string {\n return text.replaceAll(/[$()*+.?[\\\\\\]^{|}]/gu, String.raw`\\$&`);\n}\n\n/** A POSIX shell word: safe characters pass through, anything else is single-quoted. */\nexport function quoteForShell(value: string): string {\n return /^[\\w./-]+$/u.test(value) ? value : `'${value.replaceAll(\"'\", String.raw`'\\''`)}'`;\n}\n\n/**\n * Wraps text in a Markdown code block fenced with tildes, which are rarer than backticks in Markdown content.\n * The fence is longer than any run of tildes in the text so that the text cannot close it.\n */\nexport function toTildeCodeBlock(text: string, language = ''): string {\n return toFencedCodeBlock('~', text, language);\n}\n\n/**\n * Wraps text in a Markdown code block fenced with backticks.\n * The fence is longer than any run of backticks in the text so that the text cannot close it.\n */\nexport function toCodeBlock(text: string, language = ''): string {\n return toFencedCodeBlock('`', text, language);\n}\n\nfunction toFencedCodeBlock(fenceChar: string, text: string, language: string): string {\n const shortestFence = fenceChar.repeat(3);\n let longestRun = 2;\n let start = text.indexOf(shortestFence);\n while (start !== -1) {\n let end = start + 3;\n while (text[end] === fenceChar) end++;\n longestRun = Math.max(longestRun, end - start);\n start = text.indexOf(shortestFence, end);\n }\n let languageStart = 0;\n while (language[languageStart] === fenceChar) languageStart++;\n const fence = fenceChar.repeat(longestRun + 1 + languageStart);\n return `${fence}${language.slice(languageStart)}\\n${text}${text.endsWith('\\n') ? '' : '\\n'}${fence}`;\n}\n"],"mappings":"aACA,SAAgB,EAAa,EAAsB,CACjD,OAAO,EAAK,WAAW,uBAAwB,OAAO,GAAG,KAAK,CAChE,CAGA,SAAgB,EAAc,EAAuB,CACnD,MAAO,cAAc,KAAK,CAAK,EAAI,EAAQ,IAAI,EAAM,WAAW,IAAK,OAAO,GAAG,MAAM,EAAE,EACzF,CAMA,SAAgB,EAAiB,EAAc,EAAW,GAAY,CACpE,OAAO,EAAkB,IAAK,EAAM,CAAQ,CAC9C,CAMA,SAAgB,EAAY,EAAc,EAAW,GAAY,CAC/D,OAAO,EAAkB,IAAK,EAAM,CAAQ,CAC9C,CAEA,SAAS,EAAkB,EAAmB,EAAc,EAA0B,CACpF,IAAM,EAAgB,EAAU,OAAO,CAAC,EACpC,EAAa,EACb,EAAQ,EAAK,QAAQ,CAAa,EACtC,KAAO,IAAU,IAAI,CACnB,IAAI,EAAM,EAAQ,EAClB,KAAO,EAAK,KAAS,GAAW,IAChC,EAAa,KAAK,IAAI,EAAY,EAAM,CAAK,EAC7C,EAAQ,EAAK,QAAQ,EAAe,CAAG,CACzC,CACA,IAAI,EAAgB,EACpB,KAAO,EAAS,KAAmB,GAAW,IAC9C,IAAM,EAAQ,EAAU,OAAO,EAAa,EAAI,CAAa,EAC7D,MAAO,GAAG,IAAQ,EAAS,MAAM,CAAa,EAAE,IAAI,IAAO,EAAK,SAAS;CAAI,EAAI,GAAK;IAAO,GAC/F"}
1
+ {"version":3,"file":"text.cjs","names":[],"sources":["../src/text.ts"],"sourcesContent":["/** Escapes every RegExp metacharacter so the text matches itself literally. */\nexport function escapeRegExp(text: string): string {\n return text.replaceAll(/[$()*+.?[\\\\\\]^{|}]/gu, String.raw`\\$&`);\n}\n\n/** A POSIX shell word: safe characters pass through, anything else is single-quoted. */\nexport function quoteForShell(value: string): string {\n return /^[\\w./-]+$/u.test(value) ? value : `'${value.replaceAll(\"'\", String.raw`'\\''`)}'`;\n}\n\n/**\n * Wraps text in a Markdown code block fenced with tildes, which are rarer than backticks in Markdown content.\n * The fence is longer than any run of tildes in the text so that the text cannot close it.\n */\nexport function toTildeCodeBlock(text: string, language = ''): string {\n return toFencedCodeBlock('~', text, language);\n}\n\n/**\n * Wraps text in a Markdown code block fenced with backticks.\n * The fence is longer than any run of backticks in the text so that the text cannot close it.\n */\nexport function toCodeBlock(text: string, language = ''): string {\n return toFencedCodeBlock('`', text, language);\n}\n\nfunction toFencedCodeBlock(fenceChar: string, text: string, language: string): string {\n const shortestFence = fenceChar.repeat(3);\n let longestRun = 2;\n let start = text.indexOf(shortestFence);\n while (start !== -1) {\n let end = start + 3;\n while (text[end] === fenceChar) end++;\n longestRun = Math.max(longestRun, end - start);\n start = text.indexOf(shortestFence, end);\n }\n let languageStart = 0;\n while (language[languageStart] === fenceChar) languageStart++;\n const fence = fenceChar.repeat(longestRun + 1 + languageStart);\n return `${fence}${language.slice(languageStart)}\\n${text}${text.endsWith('\\n') ? '' : '\\n'}${fence}`;\n}\n\n/**\n * Shortens text to at most `maxLength` UTF-16 code units, including the `ellipsis` that marks the cut.\n * Throws a `RangeError` when `maxLength` cannot hold the ellipsis.\n */\nexport function truncate(text: string, maxLength: number, ellipsis = '…'): string {\n if (text.length <= maxLength) return text;\n if (maxLength < ellipsis.length) {\n throw new RangeError(`maxLength (${maxLength}) must be at least the ellipsis length (${ellipsis.length})`);\n }\n return `${sliceWithoutSplittingSurrogates(text, maxLength - ellipsis.length)}${ellipsis}`;\n}\n\n/**\n * Returns the first `end` code units of `text`, one fewer when the last kept unit is a high surrogate, whose low half\n * is either cut off or absent from `text`, because an unpaired surrogate is replaced with U+FFFD by encoders.\n */\nexport function sliceWithoutSplittingSurrogates(text: string, end: number): string {\n // oxlint-disable-next-line unicorn/prefer-code-point -- the check is on a single UTF-16 code unit\n const lastKeptUnit = text.charCodeAt(end - 1);\n return text.slice(0, lastKeptUnit >= 0xD8_00 && lastKeptUnit <= 0xDB_FF ? end - 1 : end);\n}\n\nconst htmlEntities: Readonly<Record<string, string>> = {\n '\"': '&quot;',\n '&': '&amp;',\n \"'\": '&#39;',\n '<': '&lt;',\n '>': '&gt;',\n};\n\nconst htmlSpecialCharactersPattern = /[\"&'<>]/gu;\n\n/** Escapes `&`, `<`, `>`, `\"`, and `'`, so the result is safe in HTML text and in quoted attribute values. */\nexport function escapeHtml(text: string): string {\n // Measured in V8 and JavaScriptCore: a native `search` first is faster than `replaceAll` alone for text without these\n // characters, and one native `replaceAll` beats a per-code-unit loop for text where they are rare.\n return text.search(htmlSpecialCharactersPattern) === -1\n ? text\n : text.replaceAll(htmlSpecialCharactersPattern, (character) => htmlEntities[character] as string);\n}\n"],"mappings":"aACA,SAAgB,EAAa,EAAsB,CACjD,OAAO,EAAK,WAAW,uBAAwB,OAAO,GAAG,KAAK,CAChE,CAGA,SAAgB,EAAc,EAAuB,CACnD,MAAO,cAAc,KAAK,CAAK,EAAI,EAAQ,IAAI,EAAM,WAAW,IAAK,OAAO,GAAG,MAAM,EAAE,EACzF,CAMA,SAAgB,EAAiB,EAAc,EAAW,GAAY,CACpE,OAAO,EAAkB,IAAK,EAAM,CAAQ,CAC9C,CAMA,SAAgB,EAAY,EAAc,EAAW,GAAY,CAC/D,OAAO,EAAkB,IAAK,EAAM,CAAQ,CAC9C,CAEA,SAAS,EAAkB,EAAmB,EAAc,EAA0B,CACpF,IAAM,EAAgB,EAAU,OAAO,CAAC,EACpC,EAAa,EACb,EAAQ,EAAK,QAAQ,CAAa,EACtC,KAAO,IAAU,IAAI,CACnB,IAAI,EAAM,EAAQ,EAClB,KAAO,EAAK,KAAS,GAAW,IAChC,EAAa,KAAK,IAAI,EAAY,EAAM,CAAK,EAC7C,EAAQ,EAAK,QAAQ,EAAe,CAAG,CACzC,CACA,IAAI,EAAgB,EACpB,KAAO,EAAS,KAAmB,GAAW,IAC9C,IAAM,EAAQ,EAAU,OAAO,EAAa,EAAI,CAAa,EAC7D,MAAO,GAAG,IAAQ,EAAS,MAAM,CAAa,EAAE,IAAI,IAAO,EAAK,SAAS;CAAI,EAAI,GAAK;IAAO,GAC/F,CAMA,SAAgB,EAAS,EAAc,EAAmB,EAAW,IAAa,CAChF,GAAI,EAAK,QAAU,EAAW,OAAO,EACrC,GAAI,EAAY,EAAS,OACvB,MAAU,WAAW,cAAc,EAAU,0CAA0C,EAAS,OAAO,EAAE,EAE3G,MAAO,GAAG,EAAgC,EAAM,EAAY,EAAS,MAAM,IAAI,GACjF,CAMA,SAAgB,EAAgC,EAAc,EAAqB,CAEjF,IAAM,EAAe,EAAK,WAAW,EAAM,CAAC,EAC5C,OAAO,EAAK,MAAM,EAAG,GAAgB,OAAW,GAAgB,MAAU,EAAM,EAAI,CAAG,CACzF,CAEA,MAAM,EAAiD,CACrD,IAAK,SACL,IAAK,QACL,IAAK,QACL,IAAK,OACL,IAAK,MACP,EAEM,EAA+B,YAGrC,SAAgB,EAAW,EAAsB,CAG/C,OAAO,EAAK,OAAO,CAA4B,IAAM,GACjD,EACA,EAAK,WAAW,EAA+B,GAAc,EAAa,EAAoB,CACpG"}
package/dist/text.d.ts CHANGED
@@ -12,3 +12,15 @@ export declare function toTildeCodeBlock(text: string, language?: string): strin
12
12
  * The fence is longer than any run of backticks in the text so that the text cannot close it.
13
13
  */
14
14
  export declare function toCodeBlock(text: string, language?: string): string;
15
+ /**
16
+ * Shortens text to at most `maxLength` UTF-16 code units, including the `ellipsis` that marks the cut.
17
+ * Throws a `RangeError` when `maxLength` cannot hold the ellipsis.
18
+ */
19
+ export declare function truncate(text: string, maxLength: number, ellipsis?: string): string;
20
+ /**
21
+ * Returns the first `end` code units of `text`, one fewer when the last kept unit is a high surrogate, whose low half
22
+ * is either cut off or absent from `text`, because an unpaired surrogate is replaced with U+FFFD by encoders.
23
+ */
24
+ export declare function sliceWithoutSplittingSurrogates(text: string, end: number): string;
25
+ /** Escapes `&`, `<`, `>`, `"`, and `'`, so the result is safe in HTML text and in quoted attribute values. */
26
+ export declare function escapeHtml(text: string): string;
package/dist/text.js CHANGED
@@ -1,4 +1,4 @@
1
1
  function e(e){return e.replaceAll(/[$()*+.?[\\\]^{|}]/gu,String.raw`\$&`)}function t(e){return/^[\w./-]+$/u.test(e)?e:`'${e.replaceAll(`'`,String.raw`'\''`)}'`}function n(e,t=``){return i(`~`,e,t)}function r(e,t=``){return i("`",e,t)}function i(e,t,n){let r=e.repeat(3),i=2,a=t.indexOf(r);for(;a!==-1;){let n=a+3;for(;t[n]===e;)n++;i=Math.max(i,n-a),a=t.indexOf(r,n)}let o=0;for(;n[o]===e;)o++;let s=e.repeat(i+1+o);return`${s}${n.slice(o)}\n${t}${t.endsWith(`
2
2
  `)?``:`
3
- `}${s}`}export{e as escapeRegExp,t as quoteForShell,r as toCodeBlock,n as toTildeCodeBlock};
3
+ `}${s}`}function a(e,t,n=`…`){if(e.length<=t)return e;if(t<n.length)throw RangeError(`maxLength (${t}) must be at least the ellipsis length (${n.length})`);return`${o(e,t-n.length)}${n}`}function o(e,t){let n=e.charCodeAt(t-1);return e.slice(0,n>=55296&&n<=56319?t-1:t)}const s={'"':`&quot;`,"&":`&amp;`,"'":`&#39;`,"<":`&lt;`,">":`&gt;`},c=/["&'<>]/gu;function l(e){return e.search(c)===-1?e:e.replaceAll(c,e=>s[e])}export{l as escapeHtml,e as escapeRegExp,t as quoteForShell,o as sliceWithoutSplittingSurrogates,r as toCodeBlock,n as toTildeCodeBlock,a as truncate};
4
4
  //# sourceMappingURL=text.js.map
package/dist/text.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"text.js","names":[],"sources":["../src/text.ts"],"sourcesContent":["/** Escapes every RegExp metacharacter so the text matches itself literally. */\nexport function escapeRegExp(text: string): string {\n return text.replaceAll(/[$()*+.?[\\\\\\]^{|}]/gu, String.raw`\\$&`);\n}\n\n/** A POSIX shell word: safe characters pass through, anything else is single-quoted. */\nexport function quoteForShell(value: string): string {\n return /^[\\w./-]+$/u.test(value) ? value : `'${value.replaceAll(\"'\", String.raw`'\\''`)}'`;\n}\n\n/**\n * Wraps text in a Markdown code block fenced with tildes, which are rarer than backticks in Markdown content.\n * The fence is longer than any run of tildes in the text so that the text cannot close it.\n */\nexport function toTildeCodeBlock(text: string, language = ''): string {\n return toFencedCodeBlock('~', text, language);\n}\n\n/**\n * Wraps text in a Markdown code block fenced with backticks.\n * The fence is longer than any run of backticks in the text so that the text cannot close it.\n */\nexport function toCodeBlock(text: string, language = ''): string {\n return toFencedCodeBlock('`', text, language);\n}\n\nfunction toFencedCodeBlock(fenceChar: string, text: string, language: string): string {\n const shortestFence = fenceChar.repeat(3);\n let longestRun = 2;\n let start = text.indexOf(shortestFence);\n while (start !== -1) {\n let end = start + 3;\n while (text[end] === fenceChar) end++;\n longestRun = Math.max(longestRun, end - start);\n start = text.indexOf(shortestFence, end);\n }\n let languageStart = 0;\n while (language[languageStart] === fenceChar) languageStart++;\n const fence = fenceChar.repeat(longestRun + 1 + languageStart);\n return `${fence}${language.slice(languageStart)}\\n${text}${text.endsWith('\\n') ? '' : '\\n'}${fence}`;\n}\n"],"mappings":"AACA,SAAgB,EAAa,EAAsB,CACjD,OAAO,EAAK,WAAW,uBAAwB,OAAO,GAAG,KAAK,CAChE,CAGA,SAAgB,EAAc,EAAuB,CACnD,MAAO,cAAc,KAAK,CAAK,EAAI,EAAQ,IAAI,EAAM,WAAW,IAAK,OAAO,GAAG,MAAM,EAAE,EACzF,CAMA,SAAgB,EAAiB,EAAc,EAAW,GAAY,CACpE,OAAO,EAAkB,IAAK,EAAM,CAAQ,CAC9C,CAMA,SAAgB,EAAY,EAAc,EAAW,GAAY,CAC/D,OAAO,EAAkB,IAAK,EAAM,CAAQ,CAC9C,CAEA,SAAS,EAAkB,EAAmB,EAAc,EAA0B,CACpF,IAAM,EAAgB,EAAU,OAAO,CAAC,EACpC,EAAa,EACb,EAAQ,EAAK,QAAQ,CAAa,EACtC,KAAO,IAAU,IAAI,CACnB,IAAI,EAAM,EAAQ,EAClB,KAAO,EAAK,KAAS,GAAW,IAChC,EAAa,KAAK,IAAI,EAAY,EAAM,CAAK,EAC7C,EAAQ,EAAK,QAAQ,EAAe,CAAG,CACzC,CACA,IAAI,EAAgB,EACpB,KAAO,EAAS,KAAmB,GAAW,IAC9C,IAAM,EAAQ,EAAU,OAAO,EAAa,EAAI,CAAa,EAC7D,MAAO,GAAG,IAAQ,EAAS,MAAM,CAAa,EAAE,IAAI,IAAO,EAAK,SAAS;CAAI,EAAI,GAAK;IAAO,GAC/F"}
1
+ {"version":3,"file":"text.js","names":[],"sources":["../src/text.ts"],"sourcesContent":["/** Escapes every RegExp metacharacter so the text matches itself literally. */\nexport function escapeRegExp(text: string): string {\n return text.replaceAll(/[$()*+.?[\\\\\\]^{|}]/gu, String.raw`\\$&`);\n}\n\n/** A POSIX shell word: safe characters pass through, anything else is single-quoted. */\nexport function quoteForShell(value: string): string {\n return /^[\\w./-]+$/u.test(value) ? value : `'${value.replaceAll(\"'\", String.raw`'\\''`)}'`;\n}\n\n/**\n * Wraps text in a Markdown code block fenced with tildes, which are rarer than backticks in Markdown content.\n * The fence is longer than any run of tildes in the text so that the text cannot close it.\n */\nexport function toTildeCodeBlock(text: string, language = ''): string {\n return toFencedCodeBlock('~', text, language);\n}\n\n/**\n * Wraps text in a Markdown code block fenced with backticks.\n * The fence is longer than any run of backticks in the text so that the text cannot close it.\n */\nexport function toCodeBlock(text: string, language = ''): string {\n return toFencedCodeBlock('`', text, language);\n}\n\nfunction toFencedCodeBlock(fenceChar: string, text: string, language: string): string {\n const shortestFence = fenceChar.repeat(3);\n let longestRun = 2;\n let start = text.indexOf(shortestFence);\n while (start !== -1) {\n let end = start + 3;\n while (text[end] === fenceChar) end++;\n longestRun = Math.max(longestRun, end - start);\n start = text.indexOf(shortestFence, end);\n }\n let languageStart = 0;\n while (language[languageStart] === fenceChar) languageStart++;\n const fence = fenceChar.repeat(longestRun + 1 + languageStart);\n return `${fence}${language.slice(languageStart)}\\n${text}${text.endsWith('\\n') ? '' : '\\n'}${fence}`;\n}\n\n/**\n * Shortens text to at most `maxLength` UTF-16 code units, including the `ellipsis` that marks the cut.\n * Throws a `RangeError` when `maxLength` cannot hold the ellipsis.\n */\nexport function truncate(text: string, maxLength: number, ellipsis = '…'): string {\n if (text.length <= maxLength) return text;\n if (maxLength < ellipsis.length) {\n throw new RangeError(`maxLength (${maxLength}) must be at least the ellipsis length (${ellipsis.length})`);\n }\n return `${sliceWithoutSplittingSurrogates(text, maxLength - ellipsis.length)}${ellipsis}`;\n}\n\n/**\n * Returns the first `end` code units of `text`, one fewer when the last kept unit is a high surrogate, whose low half\n * is either cut off or absent from `text`, because an unpaired surrogate is replaced with U+FFFD by encoders.\n */\nexport function sliceWithoutSplittingSurrogates(text: string, end: number): string {\n // oxlint-disable-next-line unicorn/prefer-code-point -- the check is on a single UTF-16 code unit\n const lastKeptUnit = text.charCodeAt(end - 1);\n return text.slice(0, lastKeptUnit >= 0xD8_00 && lastKeptUnit <= 0xDB_FF ? end - 1 : end);\n}\n\nconst htmlEntities: Readonly<Record<string, string>> = {\n '\"': '&quot;',\n '&': '&amp;',\n \"'\": '&#39;',\n '<': '&lt;',\n '>': '&gt;',\n};\n\nconst htmlSpecialCharactersPattern = /[\"&'<>]/gu;\n\n/** Escapes `&`, `<`, `>`, `\"`, and `'`, so the result is safe in HTML text and in quoted attribute values. */\nexport function escapeHtml(text: string): string {\n // Measured in V8 and JavaScriptCore: a native `search` first is faster than `replaceAll` alone for text without these\n // characters, and one native `replaceAll` beats a per-code-unit loop for text where they are rare.\n return text.search(htmlSpecialCharactersPattern) === -1\n ? text\n : text.replaceAll(htmlSpecialCharactersPattern, (character) => htmlEntities[character] as string);\n}\n"],"mappings":"AACA,SAAgB,EAAa,EAAsB,CACjD,OAAO,EAAK,WAAW,uBAAwB,OAAO,GAAG,KAAK,CAChE,CAGA,SAAgB,EAAc,EAAuB,CACnD,MAAO,cAAc,KAAK,CAAK,EAAI,EAAQ,IAAI,EAAM,WAAW,IAAK,OAAO,GAAG,MAAM,EAAE,EACzF,CAMA,SAAgB,EAAiB,EAAc,EAAW,GAAY,CACpE,OAAO,EAAkB,IAAK,EAAM,CAAQ,CAC9C,CAMA,SAAgB,EAAY,EAAc,EAAW,GAAY,CAC/D,OAAO,EAAkB,IAAK,EAAM,CAAQ,CAC9C,CAEA,SAAS,EAAkB,EAAmB,EAAc,EAA0B,CACpF,IAAM,EAAgB,EAAU,OAAO,CAAC,EACpC,EAAa,EACb,EAAQ,EAAK,QAAQ,CAAa,EACtC,KAAO,IAAU,IAAI,CACnB,IAAI,EAAM,EAAQ,EAClB,KAAO,EAAK,KAAS,GAAW,IAChC,EAAa,KAAK,IAAI,EAAY,EAAM,CAAK,EAC7C,EAAQ,EAAK,QAAQ,EAAe,CAAG,CACzC,CACA,IAAI,EAAgB,EACpB,KAAO,EAAS,KAAmB,GAAW,IAC9C,IAAM,EAAQ,EAAU,OAAO,EAAa,EAAI,CAAa,EAC7D,MAAO,GAAG,IAAQ,EAAS,MAAM,CAAa,EAAE,IAAI,IAAO,EAAK,SAAS;CAAI,EAAI,GAAK;IAAO,GAC/F,CAMA,SAAgB,EAAS,EAAc,EAAmB,EAAW,IAAa,CAChF,GAAI,EAAK,QAAU,EAAW,OAAO,EACrC,GAAI,EAAY,EAAS,OACvB,MAAU,WAAW,cAAc,EAAU,0CAA0C,EAAS,OAAO,EAAE,EAE3G,MAAO,GAAG,EAAgC,EAAM,EAAY,EAAS,MAAM,IAAI,GACjF,CAMA,SAAgB,EAAgC,EAAc,EAAqB,CAEjF,IAAM,EAAe,EAAK,WAAW,EAAM,CAAC,EAC5C,OAAO,EAAK,MAAM,EAAG,GAAgB,OAAW,GAAgB,MAAU,EAAM,EAAI,CAAG,CACzF,CAEA,MAAM,EAAiD,CACrD,IAAK,SACL,IAAK,QACL,IAAK,QACL,IAAK,OACL,IAAK,MACP,EAEM,EAA+B,YAGrC,SAAgB,EAAW,EAAsB,CAG/C,OAAO,EAAK,OAAO,CAA4B,IAAM,GACjD,EACA,EAAK,WAAW,EAA+B,GAAc,EAAa,EAAoB,CACpG"}
@@ -0,0 +1,2 @@
1
+ "use strict";async function e(e,t){let n;try{return await Promise.race([e.then(e=>({timedOut:!1,value:e})),new Promise(e=>{n=setTimeout(()=>e({timedOut:!0}),t)})])}finally{clearTimeout(n)}}exports.raceWithTimeout=e;
2
+ //# sourceMappingURL=timeout.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeout.cjs","names":[],"sources":["../src/timeout.ts"],"sourcesContent":["export type RaceWithTimeoutResult<T> = { timedOut: false; value: T } | { timedOut: true };\n\n/**\n * Waits for `promise` for at most `timeoutMilliseconds`. A rejection of `promise` within the limit propagates.\n * The timer is cleared as soon as either side settles, so it never keeps a process alive after the race.\n * `promise` itself is not canceled on timeout; pass an `AbortSignal` to the underlying work for that.\n */\nexport async function raceWithTimeout<T>(\n promise: Promise<T>,\n timeoutMilliseconds: number\n): Promise<RaceWithTimeoutResult<T>> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n promise.then((value) => ({ timedOut: false as const, value })),\n new Promise<{ timedOut: true }>((resolve) => {\n timer = setTimeout(() => resolve({ timedOut: true }), timeoutMilliseconds);\n }),\n ]);\n } finally {\n clearTimeout(timer);\n }\n}\n"],"mappings":"aAOA,eAAsB,EACpB,EACA,EACmC,CACnC,IAAI,EACJ,GAAI,CACF,OAAO,MAAM,QAAQ,KAAK,CACxB,EAAQ,KAAM,IAAW,CAAE,SAAU,GAAgB,OAAM,EAAE,EAC7D,IAAI,QAA6B,GAAY,CAC3C,EAAQ,eAAiB,EAAQ,CAAE,SAAU,EAAK,CAAC,EAAG,CAAmB,CAC3E,CAAC,CACH,CAAC,CACH,QAAU,CACR,aAAa,CAAK,CACpB,CACF"}
@@ -0,0 +1,12 @@
1
+ export type RaceWithTimeoutResult<T> = {
2
+ timedOut: false;
3
+ value: T;
4
+ } | {
5
+ timedOut: true;
6
+ };
7
+ /**
8
+ * Waits for `promise` for at most `timeoutMilliseconds`. A rejection of `promise` within the limit propagates.
9
+ * The timer is cleared as soon as either side settles, so it never keeps a process alive after the race.
10
+ * `promise` itself is not canceled on timeout; pass an `AbortSignal` to the underlying work for that.
11
+ */
12
+ export declare function raceWithTimeout<T>(promise: Promise<T>, timeoutMilliseconds: number): Promise<RaceWithTimeoutResult<T>>;
@@ -0,0 +1,2 @@
1
+ async function e(e,t){let n;try{return await Promise.race([e.then(e=>({timedOut:!1,value:e})),new Promise(e=>{n=setTimeout(()=>e({timedOut:!0}),t)})])}finally{clearTimeout(n)}}export{e as raceWithTimeout};
2
+ //# sourceMappingURL=timeout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeout.js","names":[],"sources":["../src/timeout.ts"],"sourcesContent":["export type RaceWithTimeoutResult<T> = { timedOut: false; value: T } | { timedOut: true };\n\n/**\n * Waits for `promise` for at most `timeoutMilliseconds`. A rejection of `promise` within the limit propagates.\n * The timer is cleared as soon as either side settles, so it never keeps a process alive after the race.\n * `promise` itself is not canceled on timeout; pass an `AbortSignal` to the underlying work for that.\n */\nexport async function raceWithTimeout<T>(\n promise: Promise<T>,\n timeoutMilliseconds: number\n): Promise<RaceWithTimeoutResult<T>> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n promise.then((value) => ({ timedOut: false as const, value })),\n new Promise<{ timedOut: true }>((resolve) => {\n timer = setTimeout(() => resolve({ timedOut: true }), timeoutMilliseconds);\n }),\n ]);\n } finally {\n clearTimeout(timer);\n }\n}\n"],"mappings":"AAOA,eAAsB,EACpB,EACA,EACmC,CACnC,IAAI,EACJ,GAAI,CACF,OAAO,MAAM,QAAQ,KAAK,CACxB,EAAQ,KAAM,IAAW,CAAE,SAAU,GAAgB,OAAM,EAAE,EAC7D,IAAI,QAA6B,GAAY,CAC3C,EAAQ,eAAiB,EAAQ,CAAE,SAAU,EAAK,CAAC,EAAG,CAAmB,CAC3E,CAAC,CACH,CAAC,CACH,QAAU,CACR,aAAa,CAAK,CACpB,CACF"}
package/dist/yaml.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";const e={blockQuote:`literal`,lineWidth:0};exports.yamlStringifyOptions=e;
2
+ //# sourceMappingURL=yaml.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yaml.cjs","names":[],"sources":["../src/yaml.ts"],"sourcesContent":["/**\n * Options for `stringify` of the `yaml` package that keep multiline strings readable: `blockQuote: 'literal'` writes\n * them as `key: |` blocks, and `lineWidth: 0` disables line wrapping.\n */\nexport const yamlStringifyOptions = { blockQuote: 'literal', lineWidth: 0 } as const;\n"],"mappings":"aAIA,MAAa,EAAuB,CAAE,WAAY,UAAW,UAAW,CAAE"}
package/dist/yaml.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Options for `stringify` of the `yaml` package that keep multiline strings readable: `blockQuote: 'literal'` writes
3
+ * them as `key: |` blocks, and `lineWidth: 0` disables line wrapping.
4
+ */
5
+ export declare const yamlStringifyOptions: {
6
+ readonly blockQuote: 'literal';
7
+ readonly lineWidth: 0;
8
+ };
package/dist/yaml.js ADDED
@@ -0,0 +1,2 @@
1
+ const e={blockQuote:`literal`,lineWidth:0};export{e as yamlStringifyOptions};
2
+ //# sourceMappingURL=yaml.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yaml.js","names":[],"sources":["../src/yaml.ts"],"sourcesContent":["/**\n * Options for `stringify` of the `yaml` package that keep multiline strings readable: `blockQuote: 'literal'` writes\n * them as `key: |` blocks, and `lineWidth: 0` disables line wrapping.\n */\nexport const yamlStringifyOptions = { blockQuote: 'literal', lineWidth: 0 } as const;\n"],"mappings":"AAIA,MAAa,EAAuB,CAAE,WAAY,UAAW,UAAW,CAAE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@willbooster/shared-lib",
3
- "version": "10.17.0",
3
+ "version": "10.19.0",
4
4
  "description": "Shared library for WillBooster projects",
5
5
  "repository": {
6
6
  "type": "git",
@@ -50,8 +50,8 @@
50
50
  "@types/node": "26.6.2",
51
51
  "@willbooster/oxfmt-config": "1.2.2",
52
52
  "@willbooster/oxlint-config": "1.4.8",
53
- "@willbooster/wb": "22.8.0",
54
- "build-ts": "21.0.17",
53
+ "@willbooster/wb": "22.10.0",
54
+ "build-ts": "21.0.19",
55
55
  "oxfmt": "0.68.0",
56
56
  "oxlint": "1.83.0",
57
57
  "oxlint-tsgolint": "7.0.2002",