effect 4.0.5 → 4.0.6

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 (985) hide show
  1. package/ai-docs/package.json +1 -1
  2. package/ai-docs/src/06_schedule/10_schedules.ts +5 -4
  3. package/ai-docs/tsconfig.json +3 -1
  4. package/dist/Array.d.ts +117 -52
  5. package/dist/Array.d.ts.map +1 -1
  6. package/dist/Array.js +41 -20
  7. package/dist/Array.js.map +1 -1
  8. package/dist/Bytes.d.ts +79 -0
  9. package/dist/Bytes.d.ts.map +1 -0
  10. package/dist/Bytes.js +109 -0
  11. package/dist/Bytes.js.map +1 -0
  12. package/dist/Channel.d.ts +181 -13
  13. package/dist/Channel.d.ts.map +1 -1
  14. package/dist/Channel.js +125 -30
  15. package/dist/Channel.js.map +1 -1
  16. package/dist/ChannelSchema.d.ts.map +1 -1
  17. package/dist/ChannelSchema.js.map +1 -1
  18. package/dist/Chunk.d.ts +39 -21
  19. package/dist/Chunk.d.ts.map +1 -1
  20. package/dist/Chunk.js +26 -17
  21. package/dist/Chunk.js.map +1 -1
  22. package/dist/Config.d.ts.map +1 -1
  23. package/dist/Config.js +8 -3
  24. package/dist/Config.js.map +1 -1
  25. package/dist/ConfigProvider.d.ts.map +1 -1
  26. package/dist/ConfigProvider.js +2 -1
  27. package/dist/ConfigProvider.js.map +1 -1
  28. package/dist/Cron.d.ts +2 -2
  29. package/dist/Cron.d.ts.map +1 -1
  30. package/dist/Cron.js +6 -3
  31. package/dist/Cron.js.map +1 -1
  32. package/dist/Duration.d.ts.map +1 -1
  33. package/dist/Duration.js +56 -16
  34. package/dist/Duration.js.map +1 -1
  35. package/dist/Effect.d.ts +487 -163
  36. package/dist/Effect.d.ts.map +1 -1
  37. package/dist/Effect.js +203 -37
  38. package/dist/Effect.js.map +1 -1
  39. package/dist/Equivalence.d.ts +2 -1
  40. package/dist/Equivalence.d.ts.map +1 -1
  41. package/dist/Equivalence.js +12 -8
  42. package/dist/Equivalence.js.map +1 -1
  43. package/dist/Exit.d.ts +24 -9
  44. package/dist/Exit.d.ts.map +1 -1
  45. package/dist/Exit.js +8 -3
  46. package/dist/Exit.js.map +1 -1
  47. package/dist/FiberHandle.d.ts +2 -0
  48. package/dist/FiberHandle.d.ts.map +1 -1
  49. package/dist/FiberHandle.js +9 -4
  50. package/dist/FiberHandle.js.map +1 -1
  51. package/dist/FiberMap.d.ts +2 -0
  52. package/dist/FiberMap.d.ts.map +1 -1
  53. package/dist/FiberMap.js +5 -2
  54. package/dist/FiberMap.js.map +1 -1
  55. package/dist/FileSystem.d.ts +5 -0
  56. package/dist/FileSystem.d.ts.map +1 -1
  57. package/dist/FileSystem.js +3 -0
  58. package/dist/FileSystem.js.map +1 -1
  59. package/dist/Graph.d.ts.map +1 -1
  60. package/dist/Graph.js.map +1 -1
  61. package/dist/HashSet.d.ts.map +1 -1
  62. package/dist/HashSet.js.map +1 -1
  63. package/dist/Iterable.d.ts.map +1 -1
  64. package/dist/Iterable.js +18 -17
  65. package/dist/Iterable.js.map +1 -1
  66. package/dist/JsonSchema.d.ts +9 -3
  67. package/dist/JsonSchema.d.ts.map +1 -1
  68. package/dist/JsonSchema.js +19 -3
  69. package/dist/JsonSchema.js.map +1 -1
  70. package/dist/Layer.d.ts.map +1 -1
  71. package/dist/Layer.js +2 -2
  72. package/dist/Layer.js.map +1 -1
  73. package/dist/ManagedRuntime.d.ts +19 -1
  74. package/dist/ManagedRuntime.d.ts.map +1 -1
  75. package/dist/ManagedRuntime.js +62 -6
  76. package/dist/ManagedRuntime.js.map +1 -1
  77. package/dist/Metric.d.ts +132 -0
  78. package/dist/Metric.d.ts.map +1 -1
  79. package/dist/Metric.js +197 -25
  80. package/dist/Metric.js.map +1 -1
  81. package/dist/MutableHashMap.d.ts.map +1 -1
  82. package/dist/MutableHashMap.js.map +1 -1
  83. package/dist/Number.js +2 -2
  84. package/dist/Number.js.map +1 -1
  85. package/dist/Optic.d.ts.map +1 -1
  86. package/dist/Optic.js.map +1 -1
  87. package/dist/Path.d.ts.map +1 -1
  88. package/dist/Path.js +8 -1
  89. package/dist/Path.js.map +1 -1
  90. package/dist/PubSub.d.ts.map +1 -1
  91. package/dist/PubSub.js +12 -7
  92. package/dist/PubSub.js.map +1 -1
  93. package/dist/Queue.d.ts +4 -1
  94. package/dist/Queue.d.ts.map +1 -1
  95. package/dist/Queue.js +4 -1
  96. package/dist/Queue.js.map +1 -1
  97. package/dist/Random.d.ts.map +1 -1
  98. package/dist/Random.js +1 -1
  99. package/dist/Random.js.map +1 -1
  100. package/dist/RcMap.d.ts +12 -7
  101. package/dist/RcMap.d.ts.map +1 -1
  102. package/dist/RcMap.js +9 -6
  103. package/dist/RcMap.js.map +1 -1
  104. package/dist/Record.d.ts +51 -0
  105. package/dist/Record.d.ts.map +1 -1
  106. package/dist/Record.js +17 -0
  107. package/dist/Record.js.map +1 -1
  108. package/dist/Ref.d.ts.map +1 -1
  109. package/dist/Ref.js.map +1 -1
  110. package/dist/References.d.ts +5 -4
  111. package/dist/References.d.ts.map +1 -1
  112. package/dist/References.js +5 -4
  113. package/dist/References.js.map +1 -1
  114. package/dist/RequestResolver.d.ts +31 -1
  115. package/dist/RequestResolver.d.ts.map +1 -1
  116. package/dist/RequestResolver.js +39 -4
  117. package/dist/RequestResolver.js.map +1 -1
  118. package/dist/Resource.js +1 -1
  119. package/dist/Resource.js.map +1 -1
  120. package/dist/Runtime.d.ts +3 -3
  121. package/dist/Runtime.d.ts.map +1 -1
  122. package/dist/Runtime.js +18 -15
  123. package/dist/Runtime.js.map +1 -1
  124. package/dist/Schedule.d.ts.map +1 -1
  125. package/dist/Schedule.js.map +1 -1
  126. package/dist/Schema.d.ts +384 -332
  127. package/dist/Schema.d.ts.map +1 -1
  128. package/dist/Schema.js +333 -19
  129. package/dist/Schema.js.map +1 -1
  130. package/dist/SchemaAST.d.ts +5 -5
  131. package/dist/SchemaAST.d.ts.map +1 -1
  132. package/dist/SchemaAST.js +24 -8
  133. package/dist/SchemaAST.js.map +1 -1
  134. package/dist/SchemaGetter.d.ts +8 -3
  135. package/dist/SchemaGetter.d.ts.map +1 -1
  136. package/dist/SchemaGetter.js +15 -5
  137. package/dist/SchemaGetter.js.map +1 -1
  138. package/dist/SchemaIssue.d.ts +4 -4
  139. package/dist/SchemaIssue.d.ts.map +1 -1
  140. package/dist/SchemaIssue.js +29 -51
  141. package/dist/SchemaIssue.js.map +1 -1
  142. package/dist/SchemaRepresentation.d.ts +56 -1
  143. package/dist/SchemaRepresentation.d.ts.map +1 -1
  144. package/dist/SchemaRepresentation.js +18 -0
  145. package/dist/SchemaRepresentation.js.map +1 -1
  146. package/dist/SchemaTransformation.d.ts +1 -1
  147. package/dist/SchemaTransformation.js +1 -1
  148. package/dist/Scope.d.ts +12 -2
  149. package/dist/Scope.d.ts.map +1 -1
  150. package/dist/Scope.js +5 -0
  151. package/dist/Scope.js.map +1 -1
  152. package/dist/ScopedCache.d.ts +10 -7
  153. package/dist/ScopedCache.d.ts.map +1 -1
  154. package/dist/ScopedCache.js +9 -5
  155. package/dist/ScopedCache.js.map +1 -1
  156. package/dist/SemVer.d.ts +1196 -0
  157. package/dist/SemVer.d.ts.map +1 -0
  158. package/dist/SemVer.js +756 -0
  159. package/dist/SemVer.js.map +1 -0
  160. package/dist/SemVerRange.d.ts +559 -0
  161. package/dist/SemVerRange.d.ts.map +1 -0
  162. package/dist/SemVerRange.js +551 -0
  163. package/dist/SemVerRange.js.map +1 -0
  164. package/dist/Sink.d.ts.map +1 -1
  165. package/dist/Sink.js +6 -2
  166. package/dist/Sink.js.map +1 -1
  167. package/dist/Stream.d.ts +235 -8
  168. package/dist/Stream.d.ts.map +1 -1
  169. package/dist/Stream.js +145 -60
  170. package/dist/Stream.js.map +1 -1
  171. package/dist/String.d.ts +4 -2
  172. package/dist/String.d.ts.map +1 -1
  173. package/dist/String.js +8 -6
  174. package/dist/String.js.map +1 -1
  175. package/dist/TextDiff.d.ts +399 -0
  176. package/dist/TextDiff.d.ts.map +1 -0
  177. package/dist/TextDiff.js +634 -0
  178. package/dist/TextDiff.js.map +1 -0
  179. package/dist/TxHashMap.d.ts.map +1 -1
  180. package/dist/TxHashMap.js.map +1 -1
  181. package/dist/TxHashSet.d.ts.map +1 -1
  182. package/dist/TxHashSet.js.map +1 -1
  183. package/dist/ai/AiError.d.ts +68 -4
  184. package/dist/ai/AiError.d.ts.map +1 -1
  185. package/dist/ai/AiError.js +50 -2
  186. package/dist/ai/AiError.js.map +1 -1
  187. package/dist/ai/Chat.d.ts +1 -2
  188. package/dist/ai/Chat.d.ts.map +1 -1
  189. package/dist/ai/Chat.js +6 -3
  190. package/dist/ai/Chat.js.map +1 -1
  191. package/dist/ai/Decision.d.ts +46 -1
  192. package/dist/ai/Decision.d.ts.map +1 -1
  193. package/dist/ai/Decision.js.map +1 -1
  194. package/dist/ai/DecisionModel.d.ts +129 -11
  195. package/dist/ai/DecisionModel.d.ts.map +1 -1
  196. package/dist/ai/DecisionModel.js +182 -94
  197. package/dist/ai/DecisionModel.js.map +1 -1
  198. package/dist/ai/EmbeddingModel.d.ts +10 -0
  199. package/dist/ai/EmbeddingModel.d.ts.map +1 -1
  200. package/dist/ai/EmbeddingModel.js +21 -7
  201. package/dist/ai/EmbeddingModel.js.map +1 -1
  202. package/dist/ai/McpClient.d.ts +289 -0
  203. package/dist/ai/McpClient.d.ts.map +1 -0
  204. package/dist/ai/McpClient.js +819 -0
  205. package/dist/ai/McpClient.js.map +1 -0
  206. package/dist/ai/McpClientError.d.ts +254 -0
  207. package/dist/ai/McpClientError.d.ts.map +1 -0
  208. package/dist/ai/McpClientError.js +260 -0
  209. package/dist/ai/McpClientError.js.map +1 -0
  210. package/dist/ai/McpProtocol.d.ts +2 -2
  211. package/dist/ai/McpProtocol.d.ts.map +1 -1
  212. package/dist/ai/McpSchema.d.ts +368 -235
  213. package/dist/ai/McpSchema.d.ts.map +1 -1
  214. package/dist/ai/McpSchema.js +94 -24
  215. package/dist/ai/McpSchema.js.map +1 -1
  216. package/dist/ai/McpServer.d.ts.map +1 -1
  217. package/dist/ai/McpServer.js +25 -22
  218. package/dist/ai/McpServer.js.map +1 -1
  219. package/dist/ai/Prompt.d.ts +22 -20
  220. package/dist/ai/Prompt.d.ts.map +1 -1
  221. package/dist/ai/Prompt.js +23 -1
  222. package/dist/ai/Prompt.js.map +1 -1
  223. package/dist/ai/Response.d.ts +147 -3
  224. package/dist/ai/Response.d.ts.map +1 -1
  225. package/dist/ai/Response.js +35 -37
  226. package/dist/ai/Response.js.map +1 -1
  227. package/dist/ai/Tool.d.ts +12 -4
  228. package/dist/ai/Tool.d.ts.map +1 -1
  229. package/dist/ai/Tool.js.map +1 -1
  230. package/dist/ai/Toolkit.d.ts +48 -1
  231. package/dist/ai/Toolkit.d.ts.map +1 -1
  232. package/dist/ai/Toolkit.js +65 -12
  233. package/dist/ai/Toolkit.js.map +1 -1
  234. package/dist/ai/index.d.ts +10 -0
  235. package/dist/ai/index.d.ts.map +1 -1
  236. package/dist/ai/index.js +10 -0
  237. package/dist/ai/index.js.map +1 -1
  238. package/dist/ai/internal/mcpCore.js.map +1 -1
  239. package/dist/ai/internal/mcpProtocol/v2024_11_05.js +1 -1
  240. package/dist/ai/internal/mcpProtocol/v2024_11_05.js.map +1 -1
  241. package/dist/ai/internal/mcpProtocol/v2025_03_26.js +1 -1
  242. package/dist/ai/internal/mcpProtocol/v2025_03_26.js.map +1 -1
  243. package/dist/ai/internal/mcpProtocol/v2025_06_18.js +2 -2
  244. package/dist/ai/internal/mcpProtocol/v2025_06_18.js.map +1 -1
  245. package/dist/ai/internal/mcpProtocol/v2025_11_25.js +2 -2
  246. package/dist/ai/internal/mcpProtocol/v2025_11_25.js.map +1 -1
  247. package/dist/ai/internal/mcpProtocol/v2026_07_28.js +4 -7
  248. package/dist/ai/internal/mcpProtocol/v2026_07_28.js.map +1 -1
  249. package/dist/ai/internal/mcpProtocol.js +16 -2
  250. package/dist/ai/internal/mcpProtocol.js.map +1 -1
  251. package/dist/ai/internal/mcpRuntime.js +3 -4
  252. package/dist/ai/internal/mcpRuntime.js.map +1 -1
  253. package/dist/ai/internal/mcpSchema/v2024_11_05.js +19 -13
  254. package/dist/ai/internal/mcpSchema/v2024_11_05.js.map +1 -1
  255. package/dist/ai/internal/mcpSchema/v2025_03_26.js +3 -2
  256. package/dist/ai/internal/mcpSchema/v2025_03_26.js.map +1 -1
  257. package/dist/ai/internal/mcpSchema/v2025_06_18.js +7 -7
  258. package/dist/ai/internal/mcpSchema/v2025_06_18.js.map +1 -1
  259. package/dist/ai/internal/mcpSchema/v2025_11_25.js +8 -8
  260. package/dist/ai/internal/mcpSchema/v2025_11_25.js.map +1 -1
  261. package/dist/ai/internal/mcpSchema/v2026_07_28.js +43 -42
  262. package/dist/ai/internal/mcpSchema/v2026_07_28.js.map +1 -1
  263. package/dist/cli/CliError.d.ts +42 -2
  264. package/dist/cli/CliError.d.ts.map +1 -1
  265. package/dist/cli/CliError.js +44 -5
  266. package/dist/cli/CliError.js.map +1 -1
  267. package/dist/cli/Command.d.ts +286 -2
  268. package/dist/cli/Command.d.ts.map +1 -1
  269. package/dist/cli/Command.js +107 -6
  270. package/dist/cli/Command.js.map +1 -1
  271. package/dist/cli/Completions.d.ts +5 -0
  272. package/dist/cli/Completions.d.ts.map +1 -1
  273. package/dist/cli/Completions.js.map +1 -1
  274. package/dist/cli/Flag.d.ts +115 -0
  275. package/dist/cli/Flag.d.ts.map +1 -1
  276. package/dist/cli/Flag.js +56 -0
  277. package/dist/cli/Flag.js.map +1 -1
  278. package/dist/cli/GlobalFlag.d.ts.map +1 -1
  279. package/dist/cli/GlobalFlag.js +3 -3
  280. package/dist/cli/GlobalFlag.js.map +1 -1
  281. package/dist/cli/Param.d.ts +107 -0
  282. package/dist/cli/Param.d.ts.map +1 -1
  283. package/dist/cli/Param.js +56 -0
  284. package/dist/cli/Param.js.map +1 -1
  285. package/dist/cli/TerminalCapabilities.d.ts +84 -0
  286. package/dist/cli/TerminalCapabilities.d.ts.map +1 -0
  287. package/dist/cli/TerminalCapabilities.js +122 -0
  288. package/dist/cli/TerminalCapabilities.js.map +1 -0
  289. package/dist/cli/index.d.ts +5 -0
  290. package/dist/cli/index.d.ts.map +1 -1
  291. package/dist/cli/index.js +5 -0
  292. package/dist/cli/index.js.map +1 -1
  293. package/dist/cli/internal/command.d.ts +2 -1
  294. package/dist/cli/internal/command.d.ts.map +1 -1
  295. package/dist/cli/internal/command.js +5 -2
  296. package/dist/cli/internal/command.js.map +1 -1
  297. package/dist/cli/internal/completions/bash.js +4 -3
  298. package/dist/cli/internal/completions/bash.js.map +1 -1
  299. package/dist/cli/internal/completions/descriptor.js +9 -1
  300. package/dist/cli/internal/completions/descriptor.js.map +1 -1
  301. package/dist/cli/internal/completions/fish.js +10 -8
  302. package/dist/cli/internal/completions/fish.js.map +1 -1
  303. package/dist/cli/internal/completions/powershell.js +18 -9
  304. package/dist/cli/internal/completions/powershell.js.map +1 -1
  305. package/dist/cli/internal/completions/zsh.js +8 -5
  306. package/dist/cli/internal/completions/zsh.js.map +1 -1
  307. package/dist/cli/internal/formatter.d.ts +2 -0
  308. package/dist/cli/internal/formatter.d.ts.map +1 -0
  309. package/dist/cli/internal/formatter.js +15 -0
  310. package/dist/cli/internal/formatter.js.map +1 -0
  311. package/dist/cli/internal/lexer.js +24 -10
  312. package/dist/cli/internal/lexer.js.map +1 -1
  313. package/dist/cli/internal/parser.js +24 -12
  314. package/dist/cli/internal/parser.js.map +1 -1
  315. package/dist/cluster/ClusterCron.d.ts +29 -1
  316. package/dist/cluster/ClusterCron.d.ts.map +1 -1
  317. package/dist/cluster/ClusterCron.js +64 -32
  318. package/dist/cluster/ClusterCron.js.map +1 -1
  319. package/dist/cluster/ClusterMetrics.d.ts +143 -7
  320. package/dist/cluster/ClusterMetrics.d.ts.map +1 -1
  321. package/dist/cluster/ClusterMetrics.js +151 -7
  322. package/dist/cluster/ClusterMetrics.js.map +1 -1
  323. package/dist/cluster/ClusterWorkflowEngine.d.ts +1 -1
  324. package/dist/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
  325. package/dist/cluster/ClusterWorkflowEngine.js +37 -11
  326. package/dist/cluster/ClusterWorkflowEngine.js.map +1 -1
  327. package/dist/cluster/Entity.d.ts +2 -0
  328. package/dist/cluster/Entity.d.ts.map +1 -1
  329. package/dist/cluster/Entity.js.map +1 -1
  330. package/dist/cluster/MessageStorage.d.ts +21 -0
  331. package/dist/cluster/MessageStorage.d.ts.map +1 -1
  332. package/dist/cluster/MessageStorage.js.map +1 -1
  333. package/dist/cluster/Runners.d.ts.map +1 -1
  334. package/dist/cluster/Runners.js +54 -15
  335. package/dist/cluster/Runners.js.map +1 -1
  336. package/dist/cluster/Sharding.d.ts +1 -0
  337. package/dist/cluster/Sharding.d.ts.map +1 -1
  338. package/dist/cluster/Sharding.js +95 -32
  339. package/dist/cluster/Sharding.js.map +1 -1
  340. package/dist/cluster/ShardingConfig.d.ts +20 -0
  341. package/dist/cluster/ShardingConfig.d.ts.map +1 -1
  342. package/dist/cluster/ShardingConfig.js +4 -0
  343. package/dist/cluster/ShardingConfig.js.map +1 -1
  344. package/dist/cluster/SqlMessageStorage.d.ts.map +1 -1
  345. package/dist/cluster/SqlMessageStorage.js +40 -50
  346. package/dist/cluster/SqlMessageStorage.js.map +1 -1
  347. package/dist/cluster/SqlRunnerStorage.d.ts +2 -2
  348. package/dist/cluster/SqlRunnerStorage.d.ts.map +1 -1
  349. package/dist/cluster/SqlRunnerStorage.js +10 -4
  350. package/dist/cluster/SqlRunnerStorage.js.map +1 -1
  351. package/dist/cluster/internal/entityManager.js +65 -8
  352. package/dist/cluster/internal/entityManager.js.map +1 -1
  353. package/dist/devtools/DevTools.d.ts +3 -2
  354. package/dist/devtools/DevTools.d.ts.map +1 -1
  355. package/dist/devtools/DevTools.js +3 -2
  356. package/dist/devtools/DevTools.js.map +1 -1
  357. package/dist/devtools/DevToolsClient.d.ts +11 -0
  358. package/dist/devtools/DevToolsClient.d.ts.map +1 -1
  359. package/dist/devtools/DevToolsClient.js +31 -4
  360. package/dist/devtools/DevToolsClient.js.map +1 -1
  361. package/dist/encoding/Base64Url.d.ts +29 -0
  362. package/dist/encoding/Base64Url.d.ts.map +1 -1
  363. package/dist/encoding/Base64Url.js +29 -0
  364. package/dist/encoding/Base64Url.js.map +1 -1
  365. package/dist/encoding/Ini.d.ts.map +1 -1
  366. package/dist/encoding/Ini.js +3 -0
  367. package/dist/encoding/Ini.js.map +1 -1
  368. package/dist/encoding/JsonArray.d.ts +270 -0
  369. package/dist/encoding/JsonArray.d.ts.map +1 -0
  370. package/dist/encoding/JsonArray.js +691 -0
  371. package/dist/encoding/JsonArray.js.map +1 -0
  372. package/dist/encoding/Ndjson.d.ts +43 -4
  373. package/dist/encoding/Ndjson.d.ts.map +1 -1
  374. package/dist/encoding/Ndjson.js +169 -18
  375. package/dist/encoding/Ndjson.js.map +1 -1
  376. package/dist/encoding/SchemaBinary.d.ts +9 -1
  377. package/dist/encoding/SchemaBinary.d.ts.map +1 -1
  378. package/dist/encoding/SchemaBinary.js +12 -19
  379. package/dist/encoding/SchemaBinary.js.map +1 -1
  380. package/dist/encoding/Tar.d.ts +309 -0
  381. package/dist/encoding/Tar.d.ts.map +1 -0
  382. package/dist/encoding/Tar.js +1182 -0
  383. package/dist/encoding/Tar.js.map +1 -0
  384. package/dist/encoding/Toml.js +3 -3
  385. package/dist/encoding/Toml.js.map +1 -1
  386. package/dist/encoding/Xml.d.ts +464 -0
  387. package/dist/encoding/Xml.d.ts.map +1 -0
  388. package/dist/encoding/Xml.js +1619 -0
  389. package/dist/encoding/Xml.js.map +1 -0
  390. package/dist/encoding/Yaml.d.ts +6 -2
  391. package/dist/encoding/Yaml.d.ts.map +1 -1
  392. package/dist/encoding/Yaml.js +97 -34
  393. package/dist/encoding/Yaml.js.map +1 -1
  394. package/dist/encoding/Zip.d.ts +413 -0
  395. package/dist/encoding/Zip.d.ts.map +1 -0
  396. package/dist/encoding/Zip.js +1255 -0
  397. package/dist/encoding/Zip.js.map +1 -0
  398. package/dist/encoding/index.d.ts +20 -0
  399. package/dist/encoding/index.d.ts.map +1 -1
  400. package/dist/encoding/index.js +20 -0
  401. package/dist/encoding/index.js.map +1 -1
  402. package/dist/eventlog/EventJournal.d.ts +90 -5
  403. package/dist/eventlog/EventJournal.d.ts.map +1 -1
  404. package/dist/eventlog/EventJournal.js +488 -228
  405. package/dist/eventlog/EventJournal.js.map +1 -1
  406. package/dist/eventlog/EventLog.d.ts +180 -12
  407. package/dist/eventlog/EventLog.d.ts.map +1 -1
  408. package/dist/eventlog/EventLog.js +394 -146
  409. package/dist/eventlog/EventLog.js.map +1 -1
  410. package/dist/eventlog/EventLogEncryption.d.ts +36 -30
  411. package/dist/eventlog/EventLogEncryption.d.ts.map +1 -1
  412. package/dist/eventlog/EventLogEncryption.js +97 -38
  413. package/dist/eventlog/EventLogEncryption.js.map +1 -1
  414. package/dist/eventlog/EventLogMessage.d.ts +74 -34
  415. package/dist/eventlog/EventLogMessage.d.ts.map +1 -1
  416. package/dist/eventlog/EventLogMessage.js +45 -11
  417. package/dist/eventlog/EventLogMessage.js.map +1 -1
  418. package/dist/eventlog/EventLogRemote.d.ts +45 -8
  419. package/dist/eventlog/EventLogRemote.d.ts.map +1 -1
  420. package/dist/eventlog/EventLogRemote.js +51 -14
  421. package/dist/eventlog/EventLogRemote.js.map +1 -1
  422. package/dist/eventlog/EventLogServer.d.ts +46 -3
  423. package/dist/eventlog/EventLogServer.d.ts.map +1 -1
  424. package/dist/eventlog/EventLogServer.js +119 -19
  425. package/dist/eventlog/EventLogServer.js.map +1 -1
  426. package/dist/eventlog/EventLogServerEncrypted.d.ts +23 -33
  427. package/dist/eventlog/EventLogServerEncrypted.d.ts.map +1 -1
  428. package/dist/eventlog/EventLogServerEncrypted.js +97 -70
  429. package/dist/eventlog/EventLogServerEncrypted.js.map +1 -1
  430. package/dist/eventlog/EventLogServerUnencrypted.d.ts +39 -5
  431. package/dist/eventlog/EventLogServerUnencrypted.d.ts.map +1 -1
  432. package/dist/eventlog/EventLogServerUnencrypted.js +151 -69
  433. package/dist/eventlog/EventLogServerUnencrypted.js.map +1 -1
  434. package/dist/eventlog/EventRow.d.ts +288 -0
  435. package/dist/eventlog/EventRow.d.ts.map +1 -0
  436. package/dist/eventlog/EventRow.js +435 -0
  437. package/dist/eventlog/EventRow.js.map +1 -0
  438. package/dist/eventlog/SqlEventJournal.d.ts +18 -18
  439. package/dist/eventlog/SqlEventJournal.d.ts.map +1 -1
  440. package/dist/eventlog/SqlEventJournal.js +387 -159
  441. package/dist/eventlog/SqlEventJournal.js.map +1 -1
  442. package/dist/eventlog/SqlEventLogServerEncrypted.d.ts +10 -18
  443. package/dist/eventlog/SqlEventLogServerEncrypted.d.ts.map +1 -1
  444. package/dist/eventlog/SqlEventLogServerEncrypted.js +179 -69
  445. package/dist/eventlog/SqlEventLogServerEncrypted.js.map +1 -1
  446. package/dist/eventlog/SqlEventLogServerUnencrypted.d.ts +23 -3
  447. package/dist/eventlog/SqlEventLogServerUnencrypted.d.ts.map +1 -1
  448. package/dist/eventlog/SqlEventLogServerUnencrypted.js +102 -51
  449. package/dist/eventlog/SqlEventLogServerUnencrypted.js.map +1 -1
  450. package/dist/eventlog/index.d.ts +5 -0
  451. package/dist/eventlog/index.d.ts.map +1 -1
  452. package/dist/eventlog/index.js +5 -0
  453. package/dist/eventlog/index.js.map +1 -1
  454. package/dist/eventlog/internal/conflicts.d.ts +47 -0
  455. package/dist/eventlog/internal/conflicts.d.ts.map +1 -0
  456. package/dist/eventlog/internal/conflicts.js +92 -0
  457. package/dist/eventlog/internal/conflicts.js.map +1 -0
  458. package/dist/graphql/GraphQLClientError.d.ts +2 -2
  459. package/dist/graphql/GraphQLClientError.d.ts.map +1 -1
  460. package/dist/graphql/GraphQLClientError.js +4 -18
  461. package/dist/graphql/GraphQLClientError.js.map +1 -1
  462. package/dist/graphql/GraphQLProtocol.d.ts +12 -9
  463. package/dist/graphql/GraphQLProtocol.d.ts.map +1 -1
  464. package/dist/graphql/GraphQLProtocol.js +4 -3
  465. package/dist/graphql/GraphQLProtocol.js.map +1 -1
  466. package/dist/graphql/GraphQLResolver.d.ts +2 -0
  467. package/dist/graphql/GraphQLResolver.d.ts.map +1 -1
  468. package/dist/graphql/GraphQLResolver.js +74 -32
  469. package/dist/graphql/GraphQLResolver.js.map +1 -1
  470. package/dist/http/FetchHttpClient.d.ts +8 -1
  471. package/dist/http/FetchHttpClient.d.ts.map +1 -1
  472. package/dist/http/FetchHttpClient.js +51 -4
  473. package/dist/http/FetchHttpClient.js.map +1 -1
  474. package/dist/http/FindMyWay/internal/router.js +10 -0
  475. package/dist/http/FindMyWay/internal/router.js.map +1 -1
  476. package/dist/http/Headers.d.ts +227 -0
  477. package/dist/http/Headers.d.ts.map +1 -1
  478. package/dist/http/Headers.js +261 -0
  479. package/dist/http/Headers.js.map +1 -1
  480. package/dist/http/HttpClient.d.ts +93 -0
  481. package/dist/http/HttpClient.d.ts.map +1 -1
  482. package/dist/http/HttpClient.js +55 -16
  483. package/dist/http/HttpClient.js.map +1 -1
  484. package/dist/http/HttpClientRequest.d.ts +127 -3
  485. package/dist/http/HttpClientRequest.d.ts.map +1 -1
  486. package/dist/http/HttpClientRequest.js +44 -2
  487. package/dist/http/HttpClientRequest.js.map +1 -1
  488. package/dist/http/HttpClientResponse.d.ts +53 -0
  489. package/dist/http/HttpClientResponse.d.ts.map +1 -1
  490. package/dist/http/HttpClientResponse.js +47 -0
  491. package/dist/http/HttpClientResponse.js.map +1 -1
  492. package/dist/http/HttpEffect.d.ts +6 -2
  493. package/dist/http/HttpEffect.d.ts.map +1 -1
  494. package/dist/http/HttpEffect.js +21 -17
  495. package/dist/http/HttpEffect.js.map +1 -1
  496. package/dist/http/HttpIncomingMessage.d.ts +2 -1
  497. package/dist/http/HttpIncomingMessage.d.ts.map +1 -1
  498. package/dist/http/HttpIncomingMessage.js +3 -23
  499. package/dist/http/HttpIncomingMessage.js.map +1 -1
  500. package/dist/http/HttpMiddleware.d.ts +119 -2
  501. package/dist/http/HttpMiddleware.d.ts.map +1 -1
  502. package/dist/http/HttpMiddleware.js +159 -13
  503. package/dist/http/HttpMiddleware.js.map +1 -1
  504. package/dist/http/HttpRouter.d.ts.map +1 -1
  505. package/dist/http/HttpRouter.js +7 -2
  506. package/dist/http/HttpRouter.js.map +1 -1
  507. package/dist/http/HttpServerError.d.ts +5 -2
  508. package/dist/http/HttpServerError.d.ts.map +1 -1
  509. package/dist/http/HttpServerError.js +5 -3
  510. package/dist/http/HttpServerError.js.map +1 -1
  511. package/dist/http/HttpServerRequest.d.ts +25 -5
  512. package/dist/http/HttpServerRequest.d.ts.map +1 -1
  513. package/dist/http/HttpServerRequest.js +36 -10
  514. package/dist/http/HttpServerRequest.js.map +1 -1
  515. package/dist/http/HttpServerResponse.d.ts +17 -8
  516. package/dist/http/HttpServerResponse.d.ts.map +1 -1
  517. package/dist/http/HttpServerResponse.js +37 -21
  518. package/dist/http/HttpServerResponse.js.map +1 -1
  519. package/dist/http/HttpStaticServer.d.ts +0 -12
  520. package/dist/http/HttpStaticServer.d.ts.map +1 -1
  521. package/dist/http/HttpStaticServer.js +21 -7
  522. package/dist/http/HttpStaticServer.js.map +1 -1
  523. package/dist/http/MultipartParser/internal/contentType.d.ts +15 -1
  524. package/dist/http/MultipartParser/internal/contentType.d.ts.map +1 -1
  525. package/dist/http/MultipartParser/internal/contentType.js +87 -5
  526. package/dist/http/MultipartParser/internal/contentType.js.map +1 -1
  527. package/dist/http/MultipartParser/internal/headers.d.ts.map +1 -1
  528. package/dist/http/MultipartParser/internal/headers.js +4 -12
  529. package/dist/http/MultipartParser/internal/headers.js.map +1 -1
  530. package/dist/http/MultipartParser/internal/multipart.d.ts.map +1 -1
  531. package/dist/http/MultipartParser/internal/multipart.js +6 -27
  532. package/dist/http/MultipartParser/internal/multipart.js.map +1 -1
  533. package/dist/http/Url.d.ts.map +1 -1
  534. package/dist/http/Url.js +6 -1
  535. package/dist/http/Url.js.map +1 -1
  536. package/dist/http/internal/decompression.js +17 -11
  537. package/dist/http/internal/decompression.js.map +1 -1
  538. package/dist/http/internal/lazyStream.d.ts +2 -0
  539. package/dist/http/internal/lazyStream.d.ts.map +1 -0
  540. package/dist/http/internal/lazyStream.js +18 -0
  541. package/dist/http/internal/lazyStream.js.map +1 -0
  542. package/dist/http/internal/requestState.d.ts +2 -0
  543. package/dist/http/internal/requestState.d.ts.map +1 -0
  544. package/dist/http/internal/requestState.js +28 -0
  545. package/dist/http/internal/requestState.js.map +1 -0
  546. package/dist/http/internal/webResponse.d.ts +2 -0
  547. package/dist/http/internal/webResponse.d.ts.map +1 -0
  548. package/dist/http/internal/webResponse.js +12 -0
  549. package/dist/http/internal/webResponse.js.map +1 -0
  550. package/dist/http-api/HttpApi.js +1 -1
  551. package/dist/http-api/HttpApi.js.map +1 -1
  552. package/dist/http-api/HttpApiBuilder.d.ts.map +1 -1
  553. package/dist/http-api/HttpApiBuilder.js +121 -18
  554. package/dist/http-api/HttpApiBuilder.js.map +1 -1
  555. package/dist/http-api/HttpApiClient.d.ts +29 -4
  556. package/dist/http-api/HttpApiClient.d.ts.map +1 -1
  557. package/dist/http-api/HttpApiClient.js +83 -23
  558. package/dist/http-api/HttpApiClient.js.map +1 -1
  559. package/dist/http-api/HttpApiEndpoint.d.ts +55 -29
  560. package/dist/http-api/HttpApiEndpoint.d.ts.map +1 -1
  561. package/dist/http-api/HttpApiEndpoint.js +49 -5
  562. package/dist/http-api/HttpApiEndpoint.js.map +1 -1
  563. package/dist/http-api/HttpApiError.d.ts +58 -0
  564. package/dist/http-api/HttpApiError.d.ts.map +1 -1
  565. package/dist/http-api/HttpApiError.js +38 -12
  566. package/dist/http-api/HttpApiError.js.map +1 -1
  567. package/dist/http-api/HttpApiScalar.d.ts +2 -1
  568. package/dist/http-api/HttpApiScalar.d.ts.map +1 -1
  569. package/dist/http-api/HttpApiScalar.js +6 -3
  570. package/dist/http-api/HttpApiScalar.js.map +1 -1
  571. package/dist/http-api/HttpApiSchema.d.ts +191 -9
  572. package/dist/http-api/HttpApiSchema.d.ts.map +1 -1
  573. package/dist/http-api/HttpApiSchema.js +137 -4
  574. package/dist/http-api/HttpApiSchema.js.map +1 -1
  575. package/dist/http-api/HttpApiSwagger.d.ts +5 -0
  576. package/dist/http-api/HttpApiSwagger.d.ts.map +1 -1
  577. package/dist/http-api/HttpApiSwagger.js +14 -4
  578. package/dist/http-api/HttpApiSwagger.js.map +1 -1
  579. package/dist/http-api/HttpApiTest.d.ts +13 -2
  580. package/dist/http-api/HttpApiTest.d.ts.map +1 -1
  581. package/dist/http-api/HttpApiTest.js +30 -9
  582. package/dist/http-api/HttpApiTest.js.map +1 -1
  583. package/dist/http-api/OpenApi.d.ts +17 -3
  584. package/dist/http-api/OpenApi.d.ts.map +1 -1
  585. package/dist/http-api/OpenApi.js +57 -32
  586. package/dist/http-api/OpenApi.js.map +1 -1
  587. package/dist/http-api/internal/path.js +35 -10
  588. package/dist/http-api/internal/path.js.map +1 -1
  589. package/dist/index.d.ts +20 -0
  590. package/dist/index.d.ts.map +1 -1
  591. package/dist/index.js +20 -0
  592. package/dist/index.js.map +1 -1
  593. package/dist/internal/core.js +1 -1
  594. package/dist/internal/core.js.map +1 -1
  595. package/dist/internal/dateTime.js +19 -7
  596. package/dist/internal/dateTime.js.map +1 -1
  597. package/dist/internal/effect.js +85 -74
  598. package/dist/internal/effect.js.map +1 -1
  599. package/dist/internal/hashMap.js +2 -2
  600. package/dist/internal/hashMap.js.map +1 -1
  601. package/dist/internal/hydration.d.ts +2 -0
  602. package/dist/internal/hydration.d.ts.map +1 -0
  603. package/dist/internal/hydration.js +15 -0
  604. package/dist/internal/hydration.js.map +1 -0
  605. package/dist/internal/inflate.d.ts +2 -0
  606. package/dist/internal/inflate.d.ts.map +1 -0
  607. package/dist/internal/inflate.js +680 -0
  608. package/dist/internal/inflate.js.map +1 -0
  609. package/dist/internal/record.js +6 -0
  610. package/dist/internal/record.js.map +1 -1
  611. package/dist/internal/request.js +20 -7
  612. package/dist/internal/request.js.map +1 -1
  613. package/dist/internal/schedule.js +17 -22
  614. package/dist/internal/schedule.js.map +1 -1
  615. package/dist/internal/schema/fromJsonSchemaDocument.js +136 -126
  616. package/dist/internal/schema/fromJsonSchemaDocument.js.map +1 -1
  617. package/dist/internal/schema/interpreter.js +51 -36
  618. package/dist/internal/schema/interpreter.js.map +1 -1
  619. package/dist/internal/schema/standardSchema.js +34 -33
  620. package/dist/internal/schema/standardSchema.js.map +1 -1
  621. package/dist/internal/schema/toCodeDocument.js +7 -2
  622. package/dist/internal/schema/toCodeDocument.js.map +1 -1
  623. package/dist/internal/schema/toCodec.js +86 -1
  624. package/dist/internal/schema/toCodec.js.map +1 -1
  625. package/dist/internal/schema/toFormatter.js +5 -5
  626. package/dist/internal/schema/toFormatter.js.map +1 -1
  627. package/dist/internal/schema/toJsonSchemaDocument.js +60 -38
  628. package/dist/internal/schema/toJsonSchemaDocument.js.map +1 -1
  629. package/dist/internal/trie.js +1 -3
  630. package/dist/internal/trie.js.map +1 -1
  631. package/dist/internal/uuid.js +7 -3
  632. package/dist/internal/uuid.js.map +1 -1
  633. package/dist/internal/version.js +1 -1
  634. package/dist/net/NetAddress.d.ts.map +1 -1
  635. package/dist/net/NetAddress.js +2 -8
  636. package/dist/net/NetAddress.js.map +1 -1
  637. package/dist/observability/OtlpExporter.d.ts.map +1 -1
  638. package/dist/observability/OtlpExporter.js +5 -12
  639. package/dist/observability/OtlpExporter.js.map +1 -1
  640. package/dist/observability/OtlpMetrics.d.ts.map +1 -1
  641. package/dist/observability/OtlpMetrics.js +5 -3
  642. package/dist/observability/OtlpMetrics.js.map +1 -1
  643. package/dist/observability/OtlpResource.d.ts +3 -1
  644. package/dist/observability/OtlpResource.d.ts.map +1 -1
  645. package/dist/observability/OtlpResource.js +11 -4
  646. package/dist/observability/OtlpResource.js.map +1 -1
  647. package/dist/observability/OtlpSerialization.d.ts +5 -0
  648. package/dist/observability/OtlpSerialization.d.ts.map +1 -1
  649. package/dist/observability/OtlpSerialization.js +14 -3
  650. package/dist/observability/OtlpSerialization.js.map +1 -1
  651. package/dist/observability/internal/protobuf.d.ts +0 -9
  652. package/dist/observability/internal/protobuf.d.ts.map +1 -1
  653. package/dist/observability/internal/protobuf.js +2 -10
  654. package/dist/observability/internal/protobuf.js.map +1 -1
  655. package/dist/persistence/PersistedCache.d.ts.map +1 -1
  656. package/dist/persistence/PersistedCache.js +1 -1
  657. package/dist/persistence/PersistedCache.js.map +1 -1
  658. package/dist/persistence/PersistedQueue.d.ts +6 -2
  659. package/dist/persistence/PersistedQueue.d.ts.map +1 -1
  660. package/dist/persistence/PersistedQueue.js +162 -84
  661. package/dist/persistence/PersistedQueue.js.map +1 -1
  662. package/dist/persistence/Persistence.d.ts +28 -0
  663. package/dist/persistence/Persistence.d.ts.map +1 -1
  664. package/dist/persistence/Persistence.js +36 -8
  665. package/dist/persistence/Persistence.js.map +1 -1
  666. package/dist/persistence/RateLimiter.d.ts.map +1 -1
  667. package/dist/persistence/RateLimiter.js +8 -12
  668. package/dist/persistence/RateLimiter.js.map +1 -1
  669. package/dist/persistence/UserDirectories.d.ts +129 -0
  670. package/dist/persistence/UserDirectories.d.ts.map +1 -0
  671. package/dist/persistence/UserDirectories.js +178 -0
  672. package/dist/persistence/UserDirectories.js.map +1 -0
  673. package/dist/persistence/index.d.ts +5 -0
  674. package/dist/persistence/index.d.ts.map +1 -1
  675. package/dist/persistence/index.js +5 -0
  676. package/dist/persistence/index.js.map +1 -1
  677. package/dist/process/ChildProcess.d.ts +2 -1
  678. package/dist/process/ChildProcess.d.ts.map +1 -1
  679. package/dist/process/ChildProcess.js.map +1 -1
  680. package/dist/reactivity/AsyncResult.d.ts.map +1 -1
  681. package/dist/reactivity/AsyncResult.js +1 -1
  682. package/dist/reactivity/AsyncResult.js.map +1 -1
  683. package/dist/reactivity/Atom.d.ts +69 -30
  684. package/dist/reactivity/Atom.d.ts.map +1 -1
  685. package/dist/reactivity/Atom.js +40 -15
  686. package/dist/reactivity/Atom.js.map +1 -1
  687. package/dist/reactivity/AtomHttpApi.d.ts +5 -5
  688. package/dist/reactivity/AtomHttpApi.d.ts.map +1 -1
  689. package/dist/reactivity/AtomHttpApi.js +1 -1
  690. package/dist/reactivity/AtomHttpApi.js.map +1 -1
  691. package/dist/reactivity/AtomRegistry.d.ts +2 -2
  692. package/dist/reactivity/AtomRegistry.d.ts.map +1 -1
  693. package/dist/reactivity/AtomRegistry.js +44 -9
  694. package/dist/reactivity/AtomRegistry.js.map +1 -1
  695. package/dist/reactivity/AtomRpc.d.ts +3 -3
  696. package/dist/reactivity/AtomRpc.d.ts.map +1 -1
  697. package/dist/reactivity/AtomRpc.js +1 -1
  698. package/dist/reactivity/AtomRpc.js.map +1 -1
  699. package/dist/reactivity/Hydration.d.ts.map +1 -1
  700. package/dist/reactivity/Hydration.js +46 -12
  701. package/dist/reactivity/Hydration.js.map +1 -1
  702. package/dist/reactivity/Reactivity.d.ts +71 -7
  703. package/dist/reactivity/Reactivity.d.ts.map +1 -1
  704. package/dist/reactivity/Reactivity.js +21 -12
  705. package/dist/reactivity/Reactivity.js.map +1 -1
  706. package/dist/rpc/Rpc.d.ts +18 -0
  707. package/dist/rpc/Rpc.d.ts.map +1 -1
  708. package/dist/rpc/Rpc.js +20 -0
  709. package/dist/rpc/Rpc.js.map +1 -1
  710. package/dist/rpc/RpcClient.d.ts +26 -2
  711. package/dist/rpc/RpcClient.d.ts.map +1 -1
  712. package/dist/rpc/RpcClient.js +196 -60
  713. package/dist/rpc/RpcClient.js.map +1 -1
  714. package/dist/rpc/RpcSerialization.d.ts +15 -0
  715. package/dist/rpc/RpcSerialization.d.ts.map +1 -1
  716. package/dist/rpc/RpcSerialization.js +21 -5
  717. package/dist/rpc/RpcSerialization.js.map +1 -1
  718. package/dist/rpc/RpcServer.d.ts.map +1 -1
  719. package/dist/rpc/RpcServer.js +9 -18
  720. package/dist/rpc/RpcServer.js.map +1 -1
  721. package/dist/schema/Model.d.ts +1 -1
  722. package/dist/schema/VariantSchema.d.ts +22 -3
  723. package/dist/schema/VariantSchema.d.ts.map +1 -1
  724. package/dist/schema/VariantSchema.js +32 -18
  725. package/dist/schema/VariantSchema.js.map +1 -1
  726. package/dist/socket/Socket.d.ts +23 -1
  727. package/dist/socket/Socket.d.ts.map +1 -1
  728. package/dist/socket/Socket.js +36 -3
  729. package/dist/socket/Socket.js.map +1 -1
  730. package/dist/sql/Migrator.d.ts.map +1 -1
  731. package/dist/sql/Migrator.js +15 -3
  732. package/dist/sql/Migrator.js.map +1 -1
  733. package/dist/sql/SqlClient.d.ts +143 -5
  734. package/dist/sql/SqlClient.d.ts.map +1 -1
  735. package/dist/sql/SqlClient.js +148 -27
  736. package/dist/sql/SqlClient.js.map +1 -1
  737. package/dist/sql/SqlResolver.d.ts +9 -0
  738. package/dist/sql/SqlResolver.d.ts.map +1 -1
  739. package/dist/sql/SqlResolver.js +9 -0
  740. package/dist/sql/SqlResolver.js.map +1 -1
  741. package/dist/sql/Statement.d.ts +3 -1
  742. package/dist/sql/Statement.d.ts.map +1 -1
  743. package/dist/sql/Statement.js +24 -5
  744. package/dist/sql/Statement.js.map +1 -1
  745. package/dist/testing/TestClock.d.ts.map +1 -1
  746. package/dist/testing/TestClock.js +4 -2
  747. package/dist/testing/TestClock.js.map +1 -1
  748. package/dist/testing/TestSchema.d.ts +7 -1
  749. package/dist/testing/TestSchema.d.ts.map +1 -1
  750. package/dist/testing/TestSchema.js +9 -3
  751. package/dist/testing/TestSchema.js.map +1 -1
  752. package/dist/workflow/WorkflowEngine.d.ts.map +1 -1
  753. package/dist/workflow/WorkflowEngine.js +18 -4
  754. package/dist/workflow/WorkflowEngine.js.map +1 -1
  755. package/package.json +13 -3
  756. package/src/Array.ts +128 -55
  757. package/src/Bytes.ts +111 -0
  758. package/src/Channel.ts +263 -436
  759. package/src/ChannelSchema.ts +1 -49
  760. package/src/Chunk.ts +55 -61
  761. package/src/Config.ts +12 -86
  762. package/src/ConfigProvider.ts +2 -1
  763. package/src/Cron.ts +6 -3
  764. package/src/Duration.ts +66 -16
  765. package/src/Effect.ts +502 -167
  766. package/src/Equivalence.ts +7 -4
  767. package/src/Exit.ts +24 -9
  768. package/src/FiberHandle.ts +10 -9
  769. package/src/FiberMap.ts +13 -66
  770. package/src/FileSystem.ts +10 -0
  771. package/src/Graph.ts +171 -1263
  772. package/src/HashSet.ts +0 -60
  773. package/src/Iterable.ts +15 -14
  774. package/src/JsonSchema.ts +28 -3
  775. package/src/Layer.ts +2 -2
  776. package/src/ManagedRuntime.ts +72 -6
  777. package/src/Metric.ts +249 -507
  778. package/src/MutableHashMap.ts +4 -473
  779. package/src/Number.ts +2 -2
  780. package/src/Optic.ts +17 -332
  781. package/src/Path.ts +9 -1
  782. package/src/PubSub.ts +12 -7
  783. package/src/Queue.ts +5 -37
  784. package/src/Random.ts +1 -1
  785. package/src/RcMap.ts +14 -8
  786. package/src/Record.ts +51 -0
  787. package/src/Ref.ts +7 -104
  788. package/src/References.ts +5 -4
  789. package/src/RequestResolver.ts +46 -87
  790. package/src/Resource.ts +1 -1
  791. package/src/Runtime.ts +19 -18
  792. package/src/Schedule.ts +2 -94
  793. package/src/Schema.ts +591 -356
  794. package/src/SchemaAST.ts +20 -9
  795. package/src/SchemaGetter.ts +22 -5
  796. package/src/SchemaIssue.ts +44 -53
  797. package/src/SchemaRepresentation.ts +64 -1
  798. package/src/SchemaTransformation.ts +1 -1
  799. package/src/Scope.ts +12 -2
  800. package/src/ScopedCache.ts +17 -142
  801. package/src/SemVer.ts +1528 -0
  802. package/src/SemVerRange.ts +883 -0
  803. package/src/Sink.ts +6 -2
  804. package/src/Stream.ts +334 -1011
  805. package/src/String.ts +8 -8
  806. package/src/TextDiff.ts +766 -0
  807. package/src/TxHashMap.ts +1 -103
  808. package/src/TxHashSet.ts +48 -753
  809. package/src/ai/AiError.ts +66 -4
  810. package/src/ai/Chat.ts +10 -5
  811. package/src/ai/Decision.ts +49 -1
  812. package/src/ai/DecisionModel.ts +264 -108
  813. package/src/ai/EmbeddingModel.ts +25 -13
  814. package/src/ai/McpClient.ts +1211 -0
  815. package/src/ai/McpClientError.ts +329 -0
  816. package/src/ai/McpProtocol.ts +2 -2
  817. package/src/ai/McpSchema.ts +153 -35
  818. package/src/ai/McpServer.ts +217 -220
  819. package/src/ai/Prompt.ts +49 -35
  820. package/src/ai/Response.ts +195 -65
  821. package/src/ai/Tool.ts +12 -4
  822. package/src/ai/Toolkit.ts +78 -10
  823. package/src/ai/index.ts +12 -0
  824. package/src/ai/internal/mcpCore.ts +13 -14
  825. package/src/ai/internal/mcpProtocol/v2024_11_05.ts +1 -1
  826. package/src/ai/internal/mcpProtocol/v2025_03_26.ts +1 -1
  827. package/src/ai/internal/mcpProtocol/v2025_06_18.ts +3 -3
  828. package/src/ai/internal/mcpProtocol/v2025_11_25.ts +3 -3
  829. package/src/ai/internal/mcpProtocol/v2026_07_28.ts +12 -14
  830. package/src/ai/internal/mcpProtocol.ts +22 -2
  831. package/src/ai/internal/mcpRuntime.ts +3 -4
  832. package/src/ai/internal/mcpSchema/v2024_11_05.ts +20 -13
  833. package/src/ai/internal/mcpSchema/v2025_03_26.ts +4 -2
  834. package/src/ai/internal/mcpSchema/v2025_06_18.ts +7 -7
  835. package/src/ai/internal/mcpSchema/v2025_11_25.ts +8 -8
  836. package/src/ai/internal/mcpSchema/v2026_07_28.ts +44 -42
  837. package/src/cli/CliError.ts +49 -4
  838. package/src/cli/Command.ts +316 -9
  839. package/src/cli/Completions.ts +5 -0
  840. package/src/cli/Flag.ts +117 -0
  841. package/src/cli/GlobalFlag.ts +3 -3
  842. package/src/cli/Param.ts +122 -0
  843. package/src/cli/TerminalCapabilities.ts +156 -0
  844. package/src/cli/index.ts +6 -0
  845. package/src/cli/internal/command.ts +8 -3
  846. package/src/cli/internal/completions/bash.ts +4 -3
  847. package/src/cli/internal/completions/descriptor.ts +11 -1
  848. package/src/cli/internal/completions/fish.ts +10 -8
  849. package/src/cli/internal/completions/powershell.ts +23 -14
  850. package/src/cli/internal/completions/zsh.ts +8 -5
  851. package/src/cli/internal/formatter.ts +18 -0
  852. package/src/cli/internal/lexer.ts +12 -5
  853. package/src/cli/internal/parser.ts +31 -11
  854. package/src/cluster/ClusterCron.ts +94 -35
  855. package/src/cluster/ClusterMetrics.ts +149 -7
  856. package/src/cluster/ClusterWorkflowEngine.ts +84 -41
  857. package/src/cluster/Entity.ts +4 -0
  858. package/src/cluster/MessageStorage.ts +7 -0
  859. package/src/cluster/Runners.ts +76 -25
  860. package/src/cluster/Sharding.ts +118 -38
  861. package/src/cluster/ShardingConfig.ts +15 -0
  862. package/src/cluster/SqlMessageStorage.ts +58 -55
  863. package/src/cluster/SqlRunnerStorage.ts +10 -4
  864. package/src/cluster/internal/entityManager.ts +80 -10
  865. package/src/devtools/DevTools.ts +3 -2
  866. package/src/devtools/DevToolsClient.ts +27 -10
  867. package/src/encoding/Base64Url.ts +31 -0
  868. package/src/encoding/Ini.ts +3 -0
  869. package/src/encoding/JsonArray.ts +849 -0
  870. package/src/encoding/Ndjson.ts +211 -20
  871. package/src/encoding/SchemaBinary.ts +14 -48
  872. package/src/encoding/Tar.ts +1417 -0
  873. package/src/encoding/Toml.ts +3 -3
  874. package/src/encoding/Xml.ts +2037 -0
  875. package/src/encoding/Yaml.ts +108 -36
  876. package/src/encoding/Zip.ts +1558 -0
  877. package/src/encoding/index.ts +24 -0
  878. package/src/eventlog/EventJournal.ts +611 -227
  879. package/src/eventlog/EventLog.ts +496 -196
  880. package/src/eventlog/EventLogEncryption.ts +128 -43
  881. package/src/eventlog/EventLogMessage.ts +62 -11
  882. package/src/eventlog/EventLogRemote.ts +77 -21
  883. package/src/eventlog/EventLogServer.ts +162 -20
  884. package/src/eventlog/EventLogServerEncrypted.ts +121 -80
  885. package/src/eventlog/EventLogServerUnencrypted.ts +180 -77
  886. package/src/eventlog/EventRow.ts +706 -0
  887. package/src/eventlog/SqlEventJournal.ts +453 -173
  888. package/src/eventlog/SqlEventLogServerEncrypted.ts +212 -83
  889. package/src/eventlog/SqlEventLogServerUnencrypted.ts +141 -62
  890. package/src/eventlog/index.ts +6 -0
  891. package/src/eventlog/internal/conflicts.ts +123 -0
  892. package/src/graphql/GraphQLClientError.ts +5 -12
  893. package/src/graphql/GraphQLProtocol.ts +12 -9
  894. package/src/graphql/GraphQLResolver.ts +90 -239
  895. package/src/http/FetchHttpClient.ts +56 -6
  896. package/src/http/FindMyWay/internal/router.ts +11 -0
  897. package/src/http/Headers.ts +337 -154
  898. package/src/http/HttpClient.ts +126 -135
  899. package/src/http/HttpClientRequest.ts +142 -4
  900. package/src/http/HttpClientResponse.ts +71 -0
  901. package/src/http/HttpEffect.ts +25 -33
  902. package/src/http/HttpIncomingMessage.ts +3 -23
  903. package/src/http/HttpMiddleware.ts +180 -23
  904. package/src/http/HttpRouter.ts +8 -2
  905. package/src/http/HttpServerError.ts +6 -3
  906. package/src/http/HttpServerRequest.ts +71 -12
  907. package/src/http/HttpServerResponse.ts +49 -23
  908. package/src/http/HttpStaticServer.ts +25 -9
  909. package/src/http/MultipartParser/internal/contentType.ts +107 -6
  910. package/src/http/MultipartParser/internal/headers.ts +4 -16
  911. package/src/http/MultipartParser/internal/multipart.ts +10 -32
  912. package/src/http/Url.ts +6 -1
  913. package/src/http/internal/decompression.ts +26 -17
  914. package/src/http/internal/lazyStream.ts +25 -0
  915. package/src/http/internal/requestState.ts +33 -0
  916. package/src/http/internal/webResponse.ts +20 -0
  917. package/src/http-api/HttpApi.ts +1 -1
  918. package/src/http-api/HttpApiBuilder.ts +151 -23
  919. package/src/http-api/HttpApiClient.ts +158 -30
  920. package/src/http-api/HttpApiEndpoint.ts +144 -33
  921. package/src/http-api/HttpApiError.ts +55 -0
  922. package/src/http-api/HttpApiScalar.ts +4 -3
  923. package/src/http-api/HttpApiSchema.ts +275 -13
  924. package/src/http-api/HttpApiSwagger.ts +11 -4
  925. package/src/http-api/HttpApiTest.ts +33 -9
  926. package/src/http-api/OpenApi.ts +84 -42
  927. package/src/http-api/internal/path.ts +40 -12
  928. package/src/index.ts +24 -0
  929. package/src/internal/core.ts +1 -1
  930. package/src/internal/dateTime.ts +20 -7
  931. package/src/internal/effect.ts +120 -84
  932. package/src/internal/hashMap.ts +2 -2
  933. package/src/internal/hydration.ts +15 -0
  934. package/src/internal/inflate.ts +710 -0
  935. package/src/internal/record.ts +6 -0
  936. package/src/internal/request.ts +21 -6
  937. package/src/internal/schedule.ts +20 -39
  938. package/src/internal/schema/fromJsonSchemaDocument.ts +262 -193
  939. package/src/internal/schema/interpreter.ts +58 -45
  940. package/src/internal/schema/standardSchema.ts +32 -30
  941. package/src/internal/schema/toCodeDocument.ts +8 -3
  942. package/src/internal/schema/toCodec.ts +116 -1
  943. package/src/internal/schema/toFormatter.ts +6 -6
  944. package/src/internal/schema/toJsonSchemaDocument.ts +69 -39
  945. package/src/internal/trie.ts +1 -3
  946. package/src/internal/uuid.ts +15 -10
  947. package/src/internal/version.ts +1 -1
  948. package/src/net/NetAddress.ts +2 -9
  949. package/src/observability/OtlpExporter.ts +5 -12
  950. package/src/observability/OtlpMetrics.ts +5 -3
  951. package/src/observability/OtlpResource.ts +16 -6
  952. package/src/observability/OtlpSerialization.ts +17 -3
  953. package/src/observability/internal/protobuf.ts +2 -10
  954. package/src/persistence/PersistedCache.ts +3 -1
  955. package/src/persistence/PersistedQueue.ts +223 -153
  956. package/src/persistence/Persistence.ts +64 -30
  957. package/src/persistence/RateLimiter.ts +18 -21
  958. package/src/persistence/UserDirectories.ts +273 -0
  959. package/src/persistence/index.ts +6 -0
  960. package/src/process/ChildProcess.ts +2 -1
  961. package/src/reactivity/AsyncResult.ts +4 -38
  962. package/src/reactivity/Atom.ts +134 -166
  963. package/src/reactivity/AtomHttpApi.ts +10 -16
  964. package/src/reactivity/AtomRegistry.ts +50 -29
  965. package/src/reactivity/AtomRpc.ts +6 -22
  966. package/src/reactivity/Hydration.ts +53 -12
  967. package/src/reactivity/Reactivity.ts +97 -39
  968. package/src/rpc/Rpc.ts +21 -0
  969. package/src/rpc/RpcClient.ts +279 -103
  970. package/src/rpc/RpcSerialization.ts +21 -5
  971. package/src/rpc/RpcServer.ts +11 -20
  972. package/src/schema/VariantSchema.ts +86 -22
  973. package/src/socket/Socket.ts +45 -20
  974. package/src/sql/Migrator.ts +19 -9
  975. package/src/sql/SqlClient.ts +266 -29
  976. package/src/sql/SqlResolver.ts +9 -0
  977. package/src/sql/Statement.ts +35 -8
  978. package/src/testing/TestClock.ts +4 -1
  979. package/src/testing/TestSchema.ts +9 -3
  980. package/src/workflow/WorkflowEngine.ts +34 -10
  981. package/dist/http/internal/preResponseHandler.d.ts +0 -2
  982. package/dist/http/internal/preResponseHandler.d.ts.map +0 -1
  983. package/dist/http/internal/preResponseHandler.js +0 -14
  984. package/dist/http/internal/preResponseHandler.js.map +0 -1
  985. package/src/http/internal/preResponseHandler.ts +0 -19
@@ -0,0 +1,2037 @@
1
+ /**
2
+ * Decodes and encodes XML 1.0 documents as streams of events in Effect
3
+ * channels.
4
+ *
5
+ * `decode` and `decodeString` turn UTF-8 bytes or text into events, and
6
+ * `encode` and `encodeString` write events back as XML. `elements` collects
7
+ * repeated elements, such as the items of a feed, into small trees, so that a
8
+ * large document can be processed one record at a time.
9
+ *
10
+ * The decoder checks that documents are well-formed. It never reads external
11
+ * resources and never expands entities declared in a DOCTYPE, so external
12
+ * entity (XXE) and entity expansion attacks do not apply. It does not validate
13
+ * documents against a DTD or schema, and reports names as written, without
14
+ * resolving namespaces.
15
+ *
16
+ * @stability experimental
17
+ * @since 4.0.6
18
+ */
19
+ import * as Arr from "../Array.ts"
20
+ import * as Cause from "../Cause.ts"
21
+ import * as Channel from "../Channel.ts"
22
+ import * as Data from "../Data.ts"
23
+ import * as Effect from "../Effect.ts"
24
+ import * as Predicate from "../Predicate.ts"
25
+ import * as Pull from "../Pull.ts"
26
+
27
+ const XmlErrorTypeId = "~effect/encoding/Xml/XmlError"
28
+
29
+ /**
30
+ * Error raised when XML cannot be decoded or encoded.
31
+ *
32
+ * **Details**
33
+ *
34
+ * The `kind` field identifies the failure:
35
+ *
36
+ * - `Syntax`: the input is not well-formed XML or not valid UTF-8.
37
+ * - `Unsupported`: the input uses a feature this module does not process, such
38
+ * as an entity declared in a DOCTYPE or a byte encoding other than UTF-8.
39
+ * - `Limit`: the input exceeds `maxTokenSize`, `maxDepth` or `maxElementSize`.
40
+ * - `InvalidEvent`: the events do not form a well-formed document, such as an
41
+ * end tag that does not match its start tag.
42
+ *
43
+ * Errors from `decode` and `decodeString` carry the one-based `line` and
44
+ * `column` where the problem was found, also appended to `message`. Columns
45
+ * count UTF-16 code units, and lines end at LF, CR or CRLF.
46
+ *
47
+ * @stability experimental
48
+ * @category errors
49
+ * @since 4.0.6
50
+ */
51
+ export class XmlError extends Data.TaggedError("XmlError")<{
52
+ readonly kind: "Syntax" | "Unsupported" | "Limit" | "InvalidEvent"
53
+ readonly message: string
54
+ readonly line?: number | undefined
55
+ readonly column?: number | undefined
56
+ }> {
57
+ /**
58
+ * Marks this value as an XML error for runtime guards.
59
+ *
60
+ * @stability experimental
61
+ * @since 4.0.6
62
+ */
63
+ readonly [XmlErrorTypeId] = XmlErrorTypeId
64
+ }
65
+
66
+ /**
67
+ * Checks whether a value is an `XmlError`.
68
+ *
69
+ * @stability experimental
70
+ * @category guards
71
+ * @since 4.0.6
72
+ */
73
+ export const isXmlError = (u: unknown): u is XmlError => Predicate.hasProperty(u, XmlErrorTypeId)
74
+
75
+ /**
76
+ * Event for the XML declaration at the start of a document, such as
77
+ * `<?xml version="1.0" encoding="UTF-8"?>`.
78
+ *
79
+ * **Details**
80
+ *
81
+ * `encoding` and `standalone` are present only when the declaration sets them.
82
+ *
83
+ * @stability experimental
84
+ * @category models
85
+ * @since 4.0.6
86
+ */
87
+ export interface Declaration {
88
+ readonly _tag: "Declaration"
89
+ readonly version: string
90
+ readonly encoding?: string | undefined
91
+ readonly standalone?: boolean | undefined
92
+ }
93
+
94
+ /**
95
+ * Event for a document type declaration, such as `<!DOCTYPE html>`.
96
+ *
97
+ * **Details**
98
+ *
99
+ * `publicId` and `systemId` are present only when the declaration names an
100
+ * external DTD; the DTD is never read. Whitespace in `publicId` is collapsed
101
+ * to single spaces and trimmed. The internal subset is not reported.
102
+ *
103
+ * @stability experimental
104
+ * @category models
105
+ * @since 4.0.6
106
+ */
107
+ export interface Doctype {
108
+ readonly _tag: "Doctype"
109
+ readonly name: string
110
+ readonly publicId?: string | undefined
111
+ readonly systemId?: string | undefined
112
+ }
113
+
114
+ /**
115
+ * Event for a start tag, with its attributes in document order.
116
+ *
117
+ * **Details**
118
+ *
119
+ * `name` is the qualified name as written and is the only element-name field
120
+ * the encoder reads.
121
+ *
122
+ * Attribute values have their references replaced and whitespace normalized as
123
+ * XML requires. Decoded attributes inherit nothing, so only the attributes of
124
+ * the tag are present and `__proto__` is an ordinary key. Their key order is
125
+ * document order, as XML names are never integer-like. A `structuredClone` of
126
+ * a decoded map gets `Object.prototype` back. A self-closing tag such as
127
+ * `<br/>` is decoded as a `StartElement` followed by an `EndElement`.
128
+ *
129
+ * @stability experimental
130
+ * @category models
131
+ * @since 4.0.6
132
+ */
133
+ export interface StartElement {
134
+ readonly _tag: "StartElement"
135
+ readonly name: string
136
+ readonly attributes: Readonly<Record<string, string>>
137
+ }
138
+
139
+ /**
140
+ * Event for an end tag.
141
+ *
142
+ * @stability experimental
143
+ * @category models
144
+ * @since 4.0.6
145
+ */
146
+ export interface EndElement {
147
+ readonly _tag: "EndElement"
148
+ readonly name: string
149
+ }
150
+
151
+ /**
152
+ * Event for character data inside the root element.
153
+ *
154
+ * **Details**
155
+ *
156
+ * Adjacent text, references and CDATA sections are decoded into one `Text`
157
+ * event that ends at the next tag, comment or processing instruction, however
158
+ * the input is chunked. Line endings are normalized to `\n`.
159
+ *
160
+ * @stability experimental
161
+ * @category models
162
+ * @since 4.0.6
163
+ */
164
+ export interface Text {
165
+ readonly _tag: "Text"
166
+ readonly text: string
167
+ }
168
+
169
+ /**
170
+ * Event for a comment, holding the text between `<!--` and `-->`.
171
+ *
172
+ * @stability experimental
173
+ * @category models
174
+ * @since 4.0.6
175
+ */
176
+ export interface Comment {
177
+ readonly _tag: "Comment"
178
+ readonly text: string
179
+ }
180
+
181
+ /**
182
+ * Event for a processing instruction, such as
183
+ * `<?xml-stylesheet href="style.xsl"?>`.
184
+ *
185
+ * **Details**
186
+ *
187
+ * `data` is the text after the target, without leading whitespace.
188
+ *
189
+ * @stability experimental
190
+ * @category models
191
+ * @since 4.0.6
192
+ */
193
+ export interface ProcessingInstruction {
194
+ readonly _tag: "ProcessingInstruction"
195
+ readonly target: string
196
+ readonly data: string
197
+ }
198
+
199
+ /**
200
+ * Event produced by the decoders and consumed by the encoders.
201
+ *
202
+ * @stability experimental
203
+ * @category models
204
+ * @since 4.0.6
205
+ */
206
+ export type Event =
207
+ | Declaration
208
+ | Doctype
209
+ | StartElement
210
+ | EndElement
211
+ | Text
212
+ | Comment
213
+ | ProcessingInstruction
214
+
215
+ /**
216
+ * Element collected by `elements`, with its attributes and children.
217
+ *
218
+ * **Details**
219
+ *
220
+ * Children are elements and strings of character data, in document order.
221
+ * Adjacent text is merged into one string; comments and processing
222
+ * instructions are dropped.
223
+ *
224
+ * @stability experimental
225
+ * @category models
226
+ * @since 4.0.6
227
+ */
228
+ export interface Element {
229
+ readonly name: string
230
+ readonly attributes: Readonly<Record<string, string>>
231
+ readonly children: ReadonlyArray<Element | string>
232
+ }
233
+
234
+ /**
235
+ * Options for the XML decoders.
236
+ *
237
+ * **Details**
238
+ *
239
+ * - `maxTokenSize`: the maximum length of a single token in UTF-16 code units,
240
+ * as written in the input: a tag with its attributes, a comment, a processing
241
+ * instruction, a DOCTYPE, or a text node including its references and CDATA
242
+ * sections. Defaults to 10 MiB; `Infinity` disables the limit.
243
+ * - `maxDepth`: the maximum number of nested elements. Defaults to 1024;
244
+ * `Infinity` disables the limit.
245
+ *
246
+ * Memory per token and for open element names is bounded by `maxTokenSize`.
247
+ * Invalid options throw when the channel is created.
248
+ *
249
+ * @stability experimental
250
+ * @category configuration
251
+ * @since 4.0.6
252
+ */
253
+ export interface DecodeOptions {
254
+ readonly maxTokenSize?: number | undefined
255
+ readonly maxDepth?: number | undefined
256
+ }
257
+
258
+ /**
259
+ * Options for `elements`.
260
+ *
261
+ * **Details**
262
+ *
263
+ * `maxElementSize` is the maximum size of one collected element, counted as
264
+ * the UTF-16 code units of its names, attribute names and values, and text.
265
+ * Defaults to 16 MiB; `Infinity` disables the limit. Invalid options throw when
266
+ * the channel is created.
267
+ *
268
+ * @stability experimental
269
+ * @category configuration
270
+ * @since 4.0.6
271
+ */
272
+ export interface ElementsOptions {
273
+ readonly maxElementSize?: number | undefined
274
+ }
275
+
276
+ /**
277
+ * Creates a channel that decodes XML text chunks into events.
278
+ *
279
+ * **Details**
280
+ *
281
+ * - Tokens can be split anywhere between chunks. Each output chunk holds the
282
+ * events completed by one input chunk.
283
+ * - The document must have one root element. Whitespace outside it is not
284
+ * reported.
285
+ * - A leading byte order mark is skipped, and the encoding named by the XML
286
+ * declaration is ignored.
287
+ * - Events completed before an error are emitted before the channel fails.
288
+ *
289
+ * **Gotchas**
290
+ *
291
+ * - End of input inside the root fails with a `Syntax` error ("unclosed
292
+ * element"); interruption ends the stream without this check.
293
+ * - A DOCTYPE is reported as a `Doctype` event, and its internal subset is
294
+ * skipped without checking its declarations. They are not applied, so
295
+ * default attribute values are not added, and parameter entities are not
296
+ * expanded.
297
+ * - References to entities other than `&lt;`, `&gt;`, `&amp;`, `&apos;` and
298
+ * `&quot;` fail with an `Unsupported` `XmlError` when the document has a
299
+ * DOCTYPE, and with a `Syntax` `XmlError` otherwise. Character references
300
+ * such as `&#233;` are always decoded.
301
+ * - Names are reported as written, including namespace prefixes, and `xmlns`
302
+ * declarations are ordinary attributes.
303
+ * - Tokens or aggregate open element names longer than `maxTokenSize`, and
304
+ * elements nested deeper than `maxDepth`, fail with a `Limit` `XmlError`. A
305
+ * long token can instead fail with an error found in its first
306
+ * `maxTokenSize + 1` characters.
307
+ * - Strings in events can share memory with their input chunk, so keeping a
308
+ * short string, such as an id from each record, can keep the whole chunk in
309
+ * memory. Copy strings that are kept long, for example with
310
+ * `structuredClone`.
311
+ *
312
+ * **Example** (Decoding events)
313
+ *
314
+ * ```ts import.meta.vitest
315
+ * import { Effect, Stream } from "effect"
316
+ * import { Xml } from "effect/encoding"
317
+ *
318
+ * const events = Stream.make("<note id=\"1\">Hi &amp; bye<br/></note>").pipe(
319
+ * Stream.pipeThroughChannel(Xml.decodeString()),
320
+ * Stream.map((event) => event._tag),
321
+ * Stream.runCollect
322
+ * )
323
+ * await Effect.runPromise(events) // => ["StartElement", "Text", "StartElement", "EndElement", "EndElement"]
324
+ * ```
325
+ *
326
+ * @see {@link decode} for UTF-8 byte input
327
+ * @see {@link elements} for collecting repeated elements into trees
328
+ * @see {@link encodeString} for the inverse operation
329
+ *
330
+ * @stability experimental
331
+ * @category decoding
332
+ * @since 4.0.6
333
+ */
334
+ export const decodeString = <IE = never, Done = unknown>(options?: DecodeOptions): Channel.Channel<
335
+ Arr.NonEmptyReadonlyArray<Event>,
336
+ XmlError | IE,
337
+ Done,
338
+ Arr.NonEmptyReadonlyArray<string>,
339
+ IE,
340
+ Done
341
+ > => {
342
+ const parser = makeParser(options, false)
343
+ return makeChannel<string, Event, IE, Done>(() => new TextInput(parser()))
344
+ }
345
+
346
+ /**
347
+ * Creates a channel that decodes UTF-8 XML bytes into events.
348
+ *
349
+ * **Details**
350
+ *
351
+ * Works like `decodeString` after decoding the bytes as UTF-8. Multi-byte
352
+ * characters can be split between chunks, and a leading byte order mark is
353
+ * skipped.
354
+ *
355
+ * **Gotchas**
356
+ *
357
+ * - Invalid or truncated UTF-8 fails with a `Syntax` `XmlError`.
358
+ * - An initial UTF-16 byte order mark or an XML declaration naming an encoding
359
+ * other than UTF-8 or US-ASCII fails with an `Unsupported` `XmlError`.
360
+ * Decode such bytes with a `TextDecoder` for that encoding and use `decodeString`.
361
+ *
362
+ * @see {@link decodeString} for text input and the shared gotchas
363
+ *
364
+ * @stability experimental
365
+ * @category decoding
366
+ * @since 4.0.6
367
+ */
368
+ export const decode = <IE = never, Done = unknown>(options?: DecodeOptions): Channel.Channel<
369
+ Arr.NonEmptyReadonlyArray<Event>,
370
+ XmlError | IE,
371
+ Done,
372
+ Arr.NonEmptyReadonlyArray<Uint8Array>,
373
+ IE,
374
+ Done
375
+ > => {
376
+ const parser = makeParser(options, true)
377
+ return makeChannel<Uint8Array, Event, IE, Done>(() => new Utf8Input(parser()))
378
+ }
379
+
380
+ /**
381
+ * Creates a channel that collects the elements at a path into trees.
382
+ *
383
+ * **When to use**
384
+ *
385
+ * Use to process large documents such as feeds, sitemaps or exports one record
386
+ * at a time, without holding the whole document in memory.
387
+ *
388
+ * **Details**
389
+ *
390
+ * `path` lists element names from the root, and `"*"` matches any name. Each
391
+ * element whose ancestors and own name match the path is emitted once its end
392
+ * tag arrives, with all of its descendants; everything outside the matched
393
+ * elements is skipped. Because paths start at the root, an element nested in a
394
+ * matched element is part of its tree and is not emitted separately.
395
+ *
396
+ * **Gotchas**
397
+ *
398
+ * - A path that does not start at the root element matches nothing.
399
+ * - Whitespace between child elements, such as indentation, is kept as string
400
+ * children.
401
+ * - A collected element larger than `maxElementSize` fails with a `Limit`
402
+ * `XmlError`. The size counts characters, not memory: an element with many
403
+ * small children can take many times its size in memory, so use a lower
404
+ * limit for untrusted input.
405
+ * - Events that end inside an element, or end an element that was never
406
+ * started, fail with an `InvalidEvent` `XmlError`.
407
+ * - A path that is empty or contains an invalid name throws when the channel is
408
+ * created.
409
+ *
410
+ * **Example** (Reading feed items)
411
+ *
412
+ * ```ts import.meta.vitest
413
+ * import { Effect, Stream } from "effect"
414
+ * import { Xml } from "effect/encoding"
415
+ *
416
+ * const feed = `<rss><channel><title>News</title>
417
+ * <item><title>First</title></item>
418
+ * <item><title>Second</title></item>
419
+ * </channel></rss>`
420
+ *
421
+ * const items = await Effect.runPromise(
422
+ * Stream.make(feed).pipe(
423
+ * Stream.pipeThroughChannel(Xml.decodeString()),
424
+ * Stream.pipeThroughChannel(Xml.elements(["rss", "channel", "item"])),
425
+ * Stream.runCollect
426
+ * )
427
+ * )
428
+ * items.length // => 2
429
+ * items[1] // => { name: "item", attributes: {}, children: [{ name: "title", attributes: {}, children: ["Second"] }] }
430
+ * ```
431
+ *
432
+ * @see {@link decode} for producing events from bytes
433
+ *
434
+ * @stability experimental
435
+ * @category decoding
436
+ * @since 4.0.6
437
+ */
438
+ export const elements = <IE = never, Done = unknown>(
439
+ path: ReadonlyArray<string>,
440
+ options?: ElementsOptions
441
+ ): Channel.Channel<
442
+ Arr.NonEmptyReadonlyArray<Element>,
443
+ XmlError | IE,
444
+ Done,
445
+ Arr.NonEmptyReadonlyArray<Event>,
446
+ IE,
447
+ Done
448
+ > => {
449
+ if (path.length === 0) {
450
+ throw new Error("Xml: elements path must not be empty")
451
+ }
452
+ for (const name of path) {
453
+ if (name !== "*" && !isName(name)) {
454
+ throw new Error(`Xml: invalid element name in path: ${JSON.stringify(name)}`)
455
+ }
456
+ }
457
+ const maxElementSize = checkLimit("maxElementSize", options?.maxElementSize, defaultMaxElementSize)
458
+ const segments = Array.from(path)
459
+ return makeChannel<Event, Element, IE, Done>(() => new Collector(segments, maxElementSize))
460
+ }
461
+
462
+ /**
463
+ * Creates a channel that writes events as XML text.
464
+ *
465
+ * **Details**
466
+ *
467
+ * - Each input chunk is written as one string.
468
+ * - Text escapes `&`, `<` and `>`. Attribute values are double-quoted and
469
+ * escape `&`, `<`, `"`, tabs and line breaks. Carriage returns are written
470
+ * as `&#13;` so that they survive decoding.
471
+ * - Start tags are written completely on their event. Empty elements use
472
+ * explicit closing tags, such as `<br></br>`, never self-closing tags.
473
+ * - Nothing is added between events, so whitespace comes only from `Text`
474
+ * events.
475
+ *
476
+ * **Gotchas**
477
+ *
478
+ * Events that do not form one well-formed document fail with an
479
+ * `InvalidEvent` `XmlError`, such as an end tag that does not match the open
480
+ * element, a second root element, non-whitespace text outside the root
481
+ * element, invalid names or characters, `--` in a comment, `?>` in processing
482
+ * instruction data, or a declaration that is not the first event. The stream
483
+ * must end with the root element closed.
484
+ *
485
+ * **Example** (Writing a document)
486
+ *
487
+ * ```ts import.meta.vitest
488
+ * import { Effect, Stream } from "effect"
489
+ * import { Xml } from "effect/encoding"
490
+ *
491
+ * const events: ReadonlyArray<Xml.Event> = [
492
+ * { _tag: "StartElement", name: "a", attributes: { href: "x?a=1&b=2" } },
493
+ * { _tag: "Text", text: "1 < 2" },
494
+ * { _tag: "EndElement", name: "a" }
495
+ * ]
496
+ *
497
+ * const xml = Stream.fromIterable(events).pipe(
498
+ * Stream.pipeThroughChannel(Xml.encodeString()),
499
+ * Stream.mkString
500
+ * )
501
+ * await Effect.runPromise(xml) // => '<a href="x?a=1&amp;b=2">1 &lt; 2</a>'
502
+ * ```
503
+ *
504
+ * @see {@link encode} for UTF-8 byte output
505
+ * @see {@link decodeString} for the inverse operation
506
+ *
507
+ * @stability experimental
508
+ * @category encoding
509
+ * @since 4.0.6
510
+ */
511
+ export const encodeString = <IE = never, Done = unknown>(): Channel.Channel<
512
+ Arr.NonEmptyReadonlyArray<string>,
513
+ XmlError | IE,
514
+ Done,
515
+ Arr.NonEmptyReadonlyArray<Event>,
516
+ IE,
517
+ Done
518
+ > => makeChannel<Event, string, IE, Done>(() => new Writer(false))
519
+
520
+ /**
521
+ * Creates a channel that writes events as UTF-8 XML bytes.
522
+ *
523
+ * **Details**
524
+ *
525
+ * Works like `encodeString`, with one byte array per input chunk.
526
+ *
527
+ * **Gotchas**
528
+ *
529
+ * A `Declaration` event naming an encoding other than UTF-8 fails
530
+ * with an `InvalidEvent` `XmlError`.
531
+ *
532
+ * @see {@link encodeString} for text output and the shared gotchas
533
+ *
534
+ * @stability experimental
535
+ * @category encoding
536
+ * @since 4.0.6
537
+ */
538
+ export const encode = <IE = never, Done = unknown>(): Channel.Channel<
539
+ Arr.NonEmptyReadonlyArray<Uint8Array>,
540
+ XmlError | IE,
541
+ Done,
542
+ Arr.NonEmptyReadonlyArray<Event>,
543
+ IE,
544
+ Done
545
+ > =>
546
+ Channel.map(makeChannel<Event, string, IE, Done>(() => new Writer(true)), Arr.map((text) => textEncoder.encode(text)))
547
+
548
+ const defaultMaxTokenSize = 10 * 1024 * 1024
549
+ const defaultMaxDepth = 1024
550
+ const defaultMaxElementSize = 16 * 1024 * 1024
551
+
552
+ const checkLimit = (name: string, value: number | undefined, defaultValue: number): number => {
553
+ const limit = value ?? defaultValue
554
+ if (!(limit > 0)) {
555
+ throw new Error(`Xml: ${name} must be positive, got ${limit}`)
556
+ }
557
+ return limit
558
+ }
559
+
560
+ // The per-run state of a channel. `push` and `end` add output to `out`, and
561
+ // throw `XmlError`s.
562
+ interface Machine<In, Out> {
563
+ out: Array<Out>
564
+ push(input: In): void
565
+ end(): void
566
+ }
567
+
568
+ const makeChannel = <In, Out, IE, Done>(
569
+ make: () => Machine<In, Out>
570
+ ): Channel.Channel<
571
+ Arr.NonEmptyReadonlyArray<Out>,
572
+ XmlError | IE,
573
+ Done,
574
+ Arr.NonEmptyReadonlyArray<In>,
575
+ IE,
576
+ Done
577
+ > =>
578
+ Channel.fromTransform((upstream: Pull.Pull<Arr.NonEmptyReadonlyArray<In>, IE, Done>, _scope) =>
579
+ Effect.sync(() => {
580
+ const machine = make()
581
+ let done: Pull.Pull<never, never, Done> | undefined
582
+ let failure: XmlError | undefined
583
+
584
+ // Output completed before an error is emitted before the failure
585
+ const emit = (
586
+ inputs: ReadonlyArray<In> | undefined
587
+ ): Pull.Pull<Arr.NonEmptyReadonlyArray<Out>, XmlError | IE, Done> => {
588
+ try {
589
+ if (inputs === undefined) machine.end()
590
+ else for (let i = 0; i < inputs.length; i++) machine.push(inputs[i])
591
+ } catch (error) {
592
+ if (!isXmlError(error)) throw error
593
+ failure = error
594
+ }
595
+ const out = machine.out
596
+ if (Arr.isArrayNonEmpty(out)) {
597
+ machine.out = []
598
+ return Effect.succeed(out)
599
+ }
600
+ return pull
601
+ }
602
+
603
+ const step = Pull.matchEffect(upstream, {
604
+ onSuccess: emit,
605
+ onFailure: Effect.failCause,
606
+ onDone: (value) => {
607
+ done = Cause.done(value)
608
+ return emit(undefined)
609
+ }
610
+ })
611
+ const pull: Pull.Pull<Arr.NonEmptyReadonlyArray<Out>, XmlError | IE, Done> = Effect.suspend(() =>
612
+ failure !== undefined ? Effect.fail(failure) : done ?? step
613
+ )
614
+ return pull
615
+ })
616
+ )
617
+
618
+ const makeParser = (options: DecodeOptions | undefined, bytes: boolean): () => Parser => {
619
+ const maxTokenSize = checkLimit("maxTokenSize", options?.maxTokenSize, defaultMaxTokenSize)
620
+ const maxDepth = checkLimit("maxDepth", options?.maxDepth, defaultMaxDepth)
621
+ return () => new Parser(maxTokenSize, maxDepth, bytes)
622
+ }
623
+
624
+ const textEncoder = new TextEncoder()
625
+
626
+ const TAB = 9
627
+ const LF = 10
628
+ const CR = 13
629
+ const SPACE = 32
630
+ const BANG = 33
631
+ const DQUOTE = 34
632
+ const HASH = 35
633
+ const AMPERSAND = 38
634
+ const SQUOTE = 39
635
+ const DASH = 45
636
+ const SLASH = 47
637
+ const LT = 60
638
+ const EQUALS = 61
639
+ const GT = 62
640
+ const QUESTION = 63
641
+ const LBRACKET = 91
642
+ const RBRACKET = 93
643
+ const LOWER_X = 120
644
+
645
+ const isSpace = (c: number): boolean => c === SPACE || c === LF || c === TAB || c === CR
646
+
647
+ // Characters outside the XML `Char` production, including unpaired surrogates
648
+ // oxlint-disable-next-line no-control-regex
649
+ const invalidChar = /[\0-\x08\x0B\x0C\x0E-\x1F\uFFFE\uFFFF\uD800-\uDFFF]/u
650
+
651
+ // Decoded UTF-8 has no unpaired surrogates, and without the `u` flag the
652
+ // search runs several times faster on non-ASCII text
653
+ // oxlint-disable-next-line no-control-regex
654
+ const invalidDecodedChar = /[\0-\x08\x0B\x0C\x0E-\x1F\uFFFE\uFFFF]/
655
+
656
+ // `isWellFormed` (ES2024) finds unpaired surrogates much faster than a `u`
657
+ // regex, which is slow on non-ASCII text
658
+ const isWellFormed: ((s: string) => boolean) | undefined =
659
+ typeof (String.prototype as { isWellFormed?: unknown }).isWellFormed === "function" ?
660
+ (s) => (s as unknown as { isWellFormed(): boolean }).isWellFormed() :
661
+ undefined
662
+
663
+ // Returns the index of the first character outside the XML `Char` production,
664
+ // or -1
665
+ const searchInvalid = (s: string): number =>
666
+ isWellFormed !== undefined && s.search(invalidDecodedChar) === -1 && isWellFormed(s) ? -1 : s.search(invalidChar)
667
+
668
+ const isChar = (c: number): boolean =>
669
+ c === TAB || c === LF || c === CR || (c >= 0x20 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) ||
670
+ (c >= 0x10000 && c <= 0x10FFFF)
671
+
672
+ const NAME_START = 1
673
+ const NAME_CHAR = 2
674
+ const asciiName = new Uint8Array(128)
675
+ for (let c = 0; c < 128; c++) {
676
+ if ((c >= 65 && c <= 90) || (c >= 97 && c <= 122) || c === 95 || c === 58) asciiName[c] = NAME_START | NAME_CHAR
677
+ else if ((c >= 48 && c <= 57) || c === DASH || c === 46) asciiName[c] = NAME_CHAR
678
+ }
679
+
680
+ // Name characters of XML 1.0 fifth edition. Supplementary characters are
681
+ // accepted by their surrogates, which are paired once input is validated.
682
+ const isNameStartCode = (c: number): boolean =>
683
+ c < 128 ?
684
+ (asciiName[c] & NAME_START) !== 0 :
685
+ (c >= 0xC0 && c <= 0xD6) || (c >= 0xD8 && c <= 0xF6) || (c >= 0xF8 && c <= 0x2FF) ||
686
+ (c >= 0x370 && c <= 0x37D) || (c >= 0x37F && c <= 0x1FFF) || (c >= 0x200C && c <= 0x200D) ||
687
+ (c >= 0x2070 && c <= 0x218F) || (c >= 0x2C00 && c <= 0x2FEF) || (c >= 0x3001 && c <= 0xD7FF) ||
688
+ (c >= 0xF900 && c <= 0xFDCF) || (c >= 0xFDF0 && c <= 0xFFFD) || (c >= 0xD800 && c <= 0xDB7F)
689
+
690
+ const isNameCode = (c: number): boolean =>
691
+ c < 128 ?
692
+ (asciiName[c] & NAME_CHAR) !== 0 :
693
+ isNameStartCode(c) || c === 0xB7 || (c >= 0x300 && c <= 0x36F) || (c >= 0x203F && c <= 0x2040) ||
694
+ (c >= 0xDC00 && c <= 0xDFFF)
695
+
696
+ // Returns the end of the name starting at `i`, or `i` when there is none
697
+ const scanName = (s: string, i: number, end: number): number => {
698
+ if (i >= end || !isNameStartCode(s.charCodeAt(i))) return i
699
+ i++
700
+ while (i < end && isNameCode(s.charCodeAt(i))) i++
701
+ return i
702
+ }
703
+
704
+ // Name characters exclude every invalid character but unpaired surrogates
705
+ const isName = (s: string): boolean =>
706
+ s.length > 0 && scanName(s, 0, s.length) === s.length &&
707
+ (isWellFormed !== undefined ? isWellFormed(s) : !invalidChar.test(s))
708
+
709
+ const skipSpace = (s: string, i: number, end: number): number => {
710
+ while (i < end && isSpace(s.charCodeAt(i))) i++
711
+ return i
712
+ }
713
+
714
+ const lineEndings = /\r\n?/g
715
+ const attributeWhitespace = /\r\n|[\t\n\r]/g
716
+ // Characters of an attribute value that need decoding, or are not allowed
717
+ const attributeSpecial = /[&<\t\n\r]/
718
+ const attributeWhitespaceChar = /[\t\n\r]/
719
+ // Attribute values shorter than this are scanned with a loop
720
+ const shortValue = 24
721
+ const publicIdWhitespace = /[ \r\n]+/g
722
+ const decimalDigits = /^[0-9]+$/
723
+ const hexDigits = /^[0-9a-fA-F]+$/
724
+ const versionPattern = /^1\.[0-9]+$/
725
+ const encodingPattern = /^[A-Za-z][A-Za-z0-9._-]*$/
726
+
727
+ const normalizeLines = (s: string): string => s.indexOf("\r") === -1 ? s : s.replace(lineEndings, "\n")
728
+
729
+ // Normalizes the line endings and whitespace of a literal attribute value part
730
+ const normalizeAttribute = (s: string): string => s.replace(attributeWhitespace, " ")
731
+
732
+ const isReservedTarget = (target: string): boolean => target.length === 3 && target.toLowerCase() === "xml"
733
+
734
+ const isUtf8 = (encoding: string): boolean => {
735
+ const lower = encoding.toLowerCase()
736
+ return lower === "utf-8" || lower === "us-ascii"
737
+ }
738
+
739
+ const declarationPattern =
740
+ /^[ \t\r\n]+version[ \t\r\n]*=[ \t\r\n]*(?:"(1\.[0-9]+)"|'(1\.[0-9]+)')(?:[ \t\r\n]+encoding[ \t\r\n]*=[ \t\r\n]*(?:"([A-Za-z][A-Za-z0-9._-]*)"|'([A-Za-z][A-Za-z0-9._-]*)'))?(?:[ \t\r\n]+standalone[ \t\r\n]*=[ \t\r\n]*(?:"(yes|no)"|'(yes|no)'))?[ \t\r\n]*$/
741
+
742
+ const pubidPattern = /^[ \r\na-zA-Z0-9\-'()+,./:=?;!*#@$_%]*$/
743
+
744
+ // States of `Scanner`, which finds where a token split between chunks ends
745
+ const S_START = 0
746
+ const S_TEXT = 1
747
+ const S_LT = 2 // after "<"
748
+ const S_BANG = 3 // after "<!"
749
+ const S_KEYWORD = 4 // matching the rest of "<!--", "<![CDATA[" or "<!DOCTYPE"
750
+ const S_COMMENT = 5
751
+ const S_CDATA = 6
752
+ const S_PI = 7
753
+ const S_TAG = 8
754
+ const S_DOCTYPE = 9 // a DOCTYPE before its internal subset
755
+ const S_SUBSET = 10
756
+ const S_SUBSET_LT = 11
757
+ const S_SUBSET_BANG = 12
758
+ const S_SUBSET_BANG_DASH = 13
759
+ const S_SUBSET_COMMENT = 14
760
+ const S_SUBSET_PI = 15
761
+ const S_DECLARATION = 16 // a markup declaration in the internal subset
762
+ const S_AFTER_SUBSET = 17
763
+
764
+ // Scans a token one character at a time, so that the scan can resume in the
765
+ // next chunk. A token "ends" where it is complete or where it is known to be
766
+ // malformed; the parser then reads the complete token from a single string.
767
+ class Scanner {
768
+ state = S_START
769
+ // A count of matched keyword characters or trailing "-", "]" or "?"
770
+ // characters, or an open quote
771
+ aux = 0
772
+ keyword = ""
773
+
774
+ reset(state: number): void {
775
+ this.state = state
776
+ this.aux = 0
777
+ }
778
+
779
+ // Returns an index of `s` at which the token has ended, or -1
780
+ scan(s: string, i: number): number {
781
+ const n = s.length
782
+ while (i < n) {
783
+ const c = s.charCodeAt(i)
784
+ switch (this.state) {
785
+ case S_START: {
786
+ this.state = c === LT ? S_LT : S_TEXT
787
+ if (c !== LT) continue
788
+ break
789
+ }
790
+ case S_TEXT: {
791
+ return s.indexOf("<", i)
792
+ }
793
+ case S_LT: {
794
+ if (c === BANG) {
795
+ this.state = S_BANG
796
+ } else if (c === QUESTION) {
797
+ this.reset(S_PI)
798
+ } else {
799
+ this.reset(S_TAG)
800
+ continue
801
+ }
802
+ break
803
+ }
804
+ case S_BANG: {
805
+ if (c === DASH) this.keyword = "--"
806
+ else if (c === LBRACKET) this.keyword = "[CDATA["
807
+ else if (c === 68) this.keyword = "DOCTYPE"
808
+ else return i
809
+ this.state = S_KEYWORD
810
+ this.aux = 1
811
+ break
812
+ }
813
+ case S_KEYWORD: {
814
+ if (c !== this.keyword.charCodeAt(this.aux)) return i
815
+ if (++this.aux === this.keyword.length) {
816
+ this.reset(this.keyword === "--" ? S_COMMENT : this.keyword === "DOCTYPE" ? S_DOCTYPE : S_CDATA)
817
+ }
818
+ break
819
+ }
820
+ case S_COMMENT:
821
+ case S_SUBSET_COMMENT: {
822
+ if (c === DASH) {
823
+ this.aux++
824
+ } else if (c === GT && this.aux >= 2) {
825
+ if (this.state === S_COMMENT) return i + 1
826
+ this.reset(S_SUBSET)
827
+ } else {
828
+ this.aux = 0
829
+ }
830
+ break
831
+ }
832
+ case S_CDATA: {
833
+ if (c === RBRACKET) this.aux++
834
+ else if (c === GT && this.aux >= 2) return i + 1
835
+ else this.aux = 0
836
+ break
837
+ }
838
+ case S_PI:
839
+ case S_SUBSET_PI: {
840
+ if (c === GT && this.aux === 1) {
841
+ if (this.state === S_PI) return i + 1
842
+ this.reset(S_SUBSET)
843
+ } else {
844
+ this.aux = c === QUESTION ? 1 : 0
845
+ }
846
+ break
847
+ }
848
+ case S_TAG: {
849
+ // Attribute values cannot contain "<"
850
+ if (c === LT) return i
851
+ if (this.aux === 0) {
852
+ if (c === GT) return i + 1
853
+ if (c === DQUOTE || c === SQUOTE) this.aux = c
854
+ } else if (c === this.aux) {
855
+ this.aux = 0
856
+ }
857
+ break
858
+ }
859
+ case S_DOCTYPE:
860
+ case S_DECLARATION: {
861
+ if (this.aux === 0) {
862
+ if (c === LT) return i
863
+ if (c === GT) {
864
+ if (this.state === S_DOCTYPE) return i + 1
865
+ this.reset(S_SUBSET)
866
+ } else if (c === LBRACKET && this.state === S_DOCTYPE) {
867
+ this.reset(S_SUBSET)
868
+ } else if (c === DQUOTE || c === SQUOTE) {
869
+ this.aux = c
870
+ }
871
+ } else if (c === this.aux) {
872
+ this.aux = 0
873
+ }
874
+ break
875
+ }
876
+ case S_SUBSET: {
877
+ if (c === RBRACKET) this.state = S_AFTER_SUBSET
878
+ else if (c === LT) this.state = S_SUBSET_LT
879
+ else if (c === DQUOTE || c === SQUOTE || c === GT) return i
880
+ break
881
+ }
882
+ case S_SUBSET_LT: {
883
+ if (c === BANG) this.state = S_SUBSET_BANG
884
+ else if (c === QUESTION) this.reset(S_SUBSET_PI)
885
+ else return i
886
+ break
887
+ }
888
+ case S_SUBSET_BANG: {
889
+ if (c === DASH) {
890
+ this.state = S_SUBSET_BANG_DASH
891
+ } else {
892
+ this.reset(S_DECLARATION)
893
+ continue
894
+ }
895
+ break
896
+ }
897
+ case S_SUBSET_BANG_DASH: {
898
+ if (c !== DASH) return i
899
+ this.reset(S_SUBSET_COMMENT)
900
+ break
901
+ }
902
+ case S_AFTER_SUBSET: {
903
+ if (c === GT) return i + 1
904
+ if (!isSpace(c)) return i
905
+ break
906
+ }
907
+ }
908
+ i++
909
+ }
910
+ return -1
911
+ }
912
+ }
913
+
914
+ const PROLOG = 0
915
+ const CONTENT = 1
916
+ const EPILOG = 2
917
+
918
+ const describeToken = (s: string, i: number): string =>
919
+ s.startsWith("<!--", i) ?
920
+ "comment" :
921
+ s.startsWith("<![CDATA[", i) ?
922
+ "CDATA section" :
923
+ s.startsWith("<!DOCTYPE", i) ?
924
+ "DOCTYPE" :
925
+ s.startsWith("<?", i) ?
926
+ "processing instruction" :
927
+ s.startsWith("</", i) ?
928
+ "end tag" :
929
+ "start tag"
930
+
931
+ // Attribute maps inherit nothing, so "__proto__" is an ordinary key and no
932
+ // attribute is inherited. Instances of a constructor are fast-mode objects in
933
+ // V8, several times faster to fill and iterate than the dictionary-mode
934
+ // objects that `Object.create(null)` makes, but V8 makes a hidden class for
935
+ // every distinct key sequence, so `Parser.shapes` decides which tags get one.
936
+ const Attributes = function(this: Record<string, string>) {} as unknown as new() => Record<string, string>
937
+ Attributes.prototype = Object.freeze(Object.create(null))
938
+
939
+ const emptyAttributes: Readonly<Record<string, string>> = Object.freeze(new Attributes())
940
+
941
+ // The number of element names whose attribute order is tracked, and the
942
+ // number of attributes beyond which V8 would turn a fast-mode map into a
943
+ // dictionary anyway
944
+ const maxShapes = 256
945
+ const maxFastAttributes = 16
946
+
947
+ const pendingRun = 256
948
+
949
+ class Parser {
950
+ out: Array<Event> = []
951
+
952
+ // The text being parsed, which starts at document offset `base`
953
+ private buf = ""
954
+ private base = 0
955
+ // Number of characters received, excluding a byte order mark
956
+ received = 0
957
+ private started = false
958
+
959
+ // A token that continues in the next chunk
960
+ private pending: Array<string> | undefined
961
+ private pendingStart = 0
962
+ private pendingLength = 0
963
+ // Number of chunks added to `pending` since its last chunks were joined
964
+ private pendingAdded = 0
965
+ private readonly scanner = new Scanner()
966
+
967
+ // Line and column of document offset `counted`
968
+ private line = 1
969
+ private lineStart = 0
970
+ private counted = 0
971
+
972
+ private state = PROLOG
973
+ private readonly stack: Array<string> = []
974
+ private openNameSize = 0
975
+ // The attribute names of each element name, in the order they were first
976
+ // seen. A tag whose attributes follow that order, or extend it, gets a
977
+ // fast-mode map; one that diverges marks the element `null`, so that later
978
+ // tags get dictionary-mode maps and V8 does not get a hidden class per tag.
979
+ private readonly shapes = new Map<string, Array<string> | null>()
980
+ private doctype = false
981
+ private literalEnd = 0
982
+ // Character data that has not been emitted yet, and its size in the input
983
+ private text = ""
984
+ private textSize = 0
985
+
986
+ private readonly maxTokenSize: number
987
+ private readonly maxDepth: number
988
+ private readonly bytes: boolean
989
+ private ascii = false
990
+
991
+ constructor(maxTokenSize: number, maxDepth: number, bytes: boolean) {
992
+ this.maxTokenSize = maxTokenSize
993
+ this.maxDepth = maxDepth
994
+ this.bytes = bytes
995
+ }
996
+
997
+ // `force` parses a pending token without waiting for its end, so that an
998
+ // error found before invalid input is reported however the input is chunked
999
+ feed(chunk: string, force = false): void {
1000
+ if (chunk.length === 0 && !force) return
1001
+ if (!this.started) {
1002
+ this.started = true
1003
+ if (chunk.charCodeAt(0) === 0xFEFF) chunk = chunk.slice(1)
1004
+ }
1005
+ if (this.bytes) {
1006
+ const nonAscii = chunk.search(/[\u0080-\uFFFF]/)
1007
+ if (nonAscii !== -1) {
1008
+ // The prefix may contain the declaration that selects US-ASCII.
1009
+ this.feed(chunk.slice(0, nonAscii), true)
1010
+ if (this.ascii) throw this.error("Syntax", "invalid US-ASCII byte", this.received)
1011
+ chunk = chunk.slice(nonAscii)
1012
+ }
1013
+ }
1014
+ const invalid = this.bytes ? chunk.search(invalidDecodedChar) : searchInvalid(chunk)
1015
+ if (invalid !== -1) {
1016
+ // Parse up to the invalid character first, so that earlier errors are
1017
+ // reported first however the input is chunked
1018
+ this.consume(chunk.slice(0, invalid), true)
1019
+ const code = chunk.codePointAt(invalid)!.toString(16).toUpperCase().padStart(4, "0")
1020
+ throw this.error("Syntax", `invalid character U+${code}`, this.received)
1021
+ }
1022
+ this.consume(chunk, force)
1023
+ }
1024
+
1025
+ end(): void {
1026
+ if (this.pending !== undefined) {
1027
+ this.load(this.pending.join(""), this.pendingStart)
1028
+ this.pending = undefined
1029
+ }
1030
+ this.parse(true)
1031
+ if (this.state === PROLOG) throw this.error("Syntax", "no root element", this.received)
1032
+ if (this.state === CONTENT) {
1033
+ throw this.error("Syntax", `unclosed element <${this.stack[this.stack.length - 1]}>`, this.received)
1034
+ }
1035
+ }
1036
+
1037
+ error(kind: XmlError["kind"], message: string, at: number): XmlError {
1038
+ if (at > this.counted) {
1039
+ if (this.pending !== undefined) this.count(this.pending.join(""), this.pendingStart, at - this.pendingStart)
1040
+ else this.count(this.buf, this.base, at - this.base)
1041
+ }
1042
+ const line = this.line
1043
+ const column = at - this.lineStart + 1
1044
+ return new XmlError({ kind, message: `${message} at line ${line}, column ${column}`, line, column })
1045
+ }
1046
+
1047
+ // Advances the line count from `counted` to `to`, an index of `s`, which
1048
+ // starts at document offset `base`. Counting resumes only where parsing
1049
+ // stopped, which is never between a CR and an LF.
1050
+ private count(s: string, base: number, to: number): void {
1051
+ const i = this.counted - base
1052
+ if (i >= to) return
1053
+ let cr = s.indexOf("\r", i)
1054
+ let lf = s.indexOf("\n", i)
1055
+ while (true) {
1056
+ if (cr !== -1 && cr < to && (lf === -1 || cr < lf)) {
1057
+ this.line++
1058
+ this.lineStart = base + cr + 1
1059
+ cr = s.indexOf("\r", cr + 1)
1060
+ } else if (lf !== -1 && lf < to) {
1061
+ // The LF of a CRLF does not start a new line
1062
+ if (!(lf > 0 && s.charCodeAt(lf - 1) === CR)) this.line++
1063
+ this.lineStart = base + lf + 1
1064
+ lf = s.indexOf("\n", lf + 1)
1065
+ } else {
1066
+ break
1067
+ }
1068
+ }
1069
+ this.counted = base + to
1070
+ }
1071
+
1072
+ private syntax(message: string, i: number): XmlError {
1073
+ return this.error("Syntax", message, this.base + i)
1074
+ }
1075
+
1076
+ private tokenLimit(at: number): XmlError {
1077
+ return this.error("Limit", `token exceeds maxTokenSize of ${this.maxTokenSize}`, at)
1078
+ }
1079
+
1080
+ private consume(chunk: string, force = false): void {
1081
+ this.received += chunk.length
1082
+ if (this.pending !== undefined) {
1083
+ if (!force && this.scanner.scan(chunk, 0) === -1) {
1084
+ this.pending.push(chunk)
1085
+ this.pendingLength += chunk.length
1086
+ // Joins runs of chunks, so that a token split into many tiny chunks
1087
+ // does not take an array slot for each
1088
+ if (++this.pendingAdded === pendingRun) {
1089
+ this.pending.push(this.pending.splice(-pendingRun).join(""))
1090
+ this.pendingAdded = 0
1091
+ }
1092
+ this.checkPending()
1093
+ return
1094
+ }
1095
+ // Joining makes a flat string, which V8 reads faster than the rope that
1096
+ // concatenation makes
1097
+ this.pending.push(chunk)
1098
+ this.load(this.pending.join(""), this.pendingStart)
1099
+ this.pending = undefined
1100
+ } else {
1101
+ this.load(chunk, this.received - chunk.length)
1102
+ }
1103
+ this.parse(false)
1104
+ }
1105
+
1106
+ private load(buf: string, base: number): void {
1107
+ this.buf = buf
1108
+ this.base = base
1109
+ }
1110
+
1111
+ // Fails an incomplete token over maxTokenSize, preferring an error in the
1112
+ // first maxTokenSize + 1 characters of markup, as `parse` does
1113
+ private checkPending(): void {
1114
+ const text = this.scanner.state === S_TEXT
1115
+ if (this.pendingLength + (text ? this.textSize : 0) <= this.maxTokenSize) return
1116
+ if (!text) {
1117
+ this.load(this.pending!.join("").slice(0, this.maxTokenSize + 1), this.pendingStart)
1118
+ this.markup(this.buf, 0)
1119
+ }
1120
+ throw this.tokenLimit(this.pendingStart)
1121
+ }
1122
+
1123
+ private parse(final: boolean): void {
1124
+ const s = this.buf
1125
+ const n = s.length
1126
+ // Positions of the next "&", CR and "]]>", so that text runs are checked
1127
+ // without searching past them repeatedly
1128
+ let nextAmp = -1
1129
+ let nextCR = -1
1130
+ let nextCdataEnd = -1
1131
+ let i = 0
1132
+ while (i < n) {
1133
+ if (s.charCodeAt(i) !== LT) {
1134
+ let j = s.indexOf("<", i)
1135
+ if (j === -1) {
1136
+ if (!final) break
1137
+ j = n
1138
+ }
1139
+ if (this.state !== CONTENT) {
1140
+ this.checkSize(i, j)
1141
+ this.whitespace(s, i, j)
1142
+ } else {
1143
+ this.addText(i, j - i)
1144
+ if (nextCdataEnd < i) nextCdataEnd = indexOrEnd(s, "]]>", i)
1145
+ if (nextCdataEnd < j) throw this.syntax("\"]]>\" is not allowed in text", nextCdataEnd)
1146
+ if (nextAmp < i) nextAmp = indexOrEnd(s, "&", i)
1147
+ if (nextCR < i) nextCR = indexOrEnd(s, "\r", i)
1148
+ const raw = s.slice(i, j)
1149
+ this.text += nextAmp >= j
1150
+ ? (nextCR >= j ? raw : normalizeLines(raw))
1151
+ : this.decodeText(raw, i, false, nextCR < j)
1152
+ }
1153
+ i = j
1154
+ continue
1155
+ }
1156
+ // Markup is parsed from at most maxTokenSize + 1 characters, so that its
1157
+ // errors do not depend on how the input is chunked
1158
+ const long = n - i > this.maxTokenSize
1159
+ const end = this.markup(long ? s.slice(0, i + this.maxTokenSize + 1) : s, i)
1160
+ if (end === -1) {
1161
+ if (long) throw this.tokenLimit(this.base + i)
1162
+ if (final) throw this.syntax(`unterminated ${describeToken(s, i)}`, i)
1163
+ break
1164
+ }
1165
+ i = end
1166
+ }
1167
+ this.count(s, this.base, i)
1168
+ this.buf = ""
1169
+ if (i < n) {
1170
+ const rest = i === 0 ? s : s.slice(i)
1171
+ this.pending = [rest]
1172
+ this.pendingStart = this.base + i
1173
+ this.pendingLength = rest.length
1174
+ this.pendingAdded = 0
1175
+ // Brings the scanner to the end of the incomplete token
1176
+ this.scanner.reset(S_START)
1177
+ this.scanner.scan(rest, 0)
1178
+ this.checkPending()
1179
+ }
1180
+ }
1181
+
1182
+ private flushText(): void {
1183
+ if (this.text.length > 0) {
1184
+ this.out.push({ _tag: "Text", text: this.text })
1185
+ this.text = ""
1186
+ }
1187
+ this.textSize = 0
1188
+ }
1189
+
1190
+ // Adds the size of the text run or CDATA section at `i`. Exceeding the limit
1191
+ // is reported there, rather than at the start of the text.
1192
+ private addText(i: number, size: number): void {
1193
+ this.textSize += size
1194
+ if (this.textSize > this.maxTokenSize) {
1195
+ throw this.tokenLimit(this.base + i)
1196
+ }
1197
+ }
1198
+
1199
+ // Checks that the text run `s[i, j)` outside the root element is whitespace
1200
+ private whitespace(s: string, i: number, j: number): void {
1201
+ for (let k = i; k < j; k++) {
1202
+ if (!isSpace(s.charCodeAt(k))) {
1203
+ throw this.syntax(this.state === PROLOG ? "text before the root element" : "text after the root element", k)
1204
+ }
1205
+ }
1206
+ }
1207
+
1208
+ // Replaces references and normalizes line endings, or attribute whitespace.
1209
+ // `whitespace` is false when `raw` has nothing to normalize.
1210
+ private decodeText(raw: string, offset: number, attribute: boolean, whitespace: boolean): string {
1211
+ let out = ""
1212
+ let k = 0
1213
+ while (true) {
1214
+ const amp = raw.indexOf("&", k)
1215
+ const literal = raw.slice(k, amp === -1 ? raw.length : amp)
1216
+ out += !whitespace ? literal : attribute ? normalizeAttribute(literal) : normalizeLines(literal)
1217
+ if (amp === -1) return out
1218
+ const semicolon = raw.indexOf(";", amp + 1)
1219
+ if (semicolon === -1) throw this.syntax("unterminated reference", offset + amp)
1220
+ out += this.reference(raw, amp, semicolon, offset)
1221
+ k = semicolon + 1
1222
+ }
1223
+ }
1224
+
1225
+ // Decodes the reference `raw[amp, semicolon]`
1226
+ private reference(raw: string, amp: number, semicolon: number, offset: number): string {
1227
+ const c = raw.charCodeAt(amp + 1)
1228
+ // The predefined entities, without slicing their names
1229
+ if (c === 97) {
1230
+ if (raw.startsWith("amp;", amp + 1)) return "&"
1231
+ if (raw.startsWith("apos;", amp + 1)) return "'"
1232
+ } else if (c === 108) {
1233
+ if (raw.startsWith("lt;", amp + 1)) return "<"
1234
+ } else if (c === 103) {
1235
+ if (raw.startsWith("gt;", amp + 1)) return ">"
1236
+ } else if (c === 113) {
1237
+ if (raw.startsWith("quot;", amp + 1)) return "\""
1238
+ }
1239
+ if (c === HASH) {
1240
+ const hex = raw.charCodeAt(amp + 2) === LOWER_X
1241
+ const digits = raw.slice(amp + (hex ? 3 : 2), semicolon)
1242
+ const code = (hex ? hexDigits : decimalDigits).test(digits) ? parseInt(digits, hex ? 16 : 10) : -1
1243
+ if (!isChar(code)) throw this.syntax("invalid character reference", offset + amp)
1244
+ return String.fromCodePoint(code)
1245
+ }
1246
+ const name = raw.slice(amp + 1, semicolon)
1247
+ if (!isName(name)) throw this.syntax("invalid reference", offset + amp)
1248
+ if (this.doctype) {
1249
+ throw this.error(
1250
+ "Unsupported",
1251
+ `entity references other than the predefined entities are not supported: &${name};`,
1252
+ this.base + offset + amp
1253
+ )
1254
+ }
1255
+ throw this.syntax(`undefined entity &${name};`, offset + amp)
1256
+ }
1257
+
1258
+ // Parses the markup at `i`, and returns its end or -1 when it is incomplete
1259
+ private markup(s: string, i: number): number {
1260
+ const n = s.length
1261
+ if (i + 1 >= n) return -1
1262
+ const c = s.charCodeAt(i + 1)
1263
+ if (c === SLASH) return this.endTag(s, i)
1264
+ if (c === QUESTION) return this.processingInstruction(s, i)
1265
+ if (c !== BANG) return this.startTag(s, i)
1266
+ if (i + 2 >= n) return -1
1267
+ const keyword = s.charCodeAt(i + 2) === DASH ? "<!--" : s.charCodeAt(i + 2) === LBRACKET ? "<![CDATA[" : "<!DOCTYPE"
1268
+ if (!s.startsWith(keyword, i)) {
1269
+ if (n - i < keyword.length && keyword.startsWith(s.slice(i))) return -1
1270
+ throw this.syntax("invalid markup", i)
1271
+ }
1272
+ return keyword === "<!--"
1273
+ ? this.comment(s, i)
1274
+ : keyword === "<!DOCTYPE"
1275
+ ? this.doctypeDeclaration(s, i)
1276
+ : this.cdata(s, i)
1277
+ }
1278
+
1279
+ private checkSize(i: number, end: number): void {
1280
+ if (end - i > this.maxTokenSize) {
1281
+ throw this.tokenLimit(this.base + i)
1282
+ }
1283
+ }
1284
+
1285
+ private startTag(s: string, i: number): number {
1286
+ const n = s.length
1287
+ if (this.state === EPILOG) throw this.syntax("content after the root element", i)
1288
+ let j = scanName(s, i + 1, n)
1289
+ if (j === i + 1) throw this.syntax("invalid element name", i + 1)
1290
+ if (j >= n) return -1
1291
+ // In V8, a slice of 13 or more characters keeps its whole input chunk
1292
+ // alive, and the name of an open element is held until its end tag, so
1293
+ // long names are copied
1294
+ const name = j - i - 1 < 13 ? s.slice(i + 1, j) : (" " + s.slice(i + 1, j)).slice(1)
1295
+ let attributes: Record<string, string> | undefined
1296
+ let shape: Array<string> | null | undefined
1297
+ let index = 0
1298
+ let selfClosing = false
1299
+ while (true) {
1300
+ let c = s.charCodeAt(j)
1301
+ const space = isSpace(c)
1302
+ if (space) {
1303
+ j = skipSpace(s, j, n)
1304
+ if (j >= n) return -1
1305
+ c = s.charCodeAt(j)
1306
+ }
1307
+ if (c === GT) {
1308
+ j++
1309
+ break
1310
+ }
1311
+ if (c === SLASH) {
1312
+ if (j + 1 >= n) return -1
1313
+ if (s.charCodeAt(j + 1) !== GT) throw this.syntax("expected \">\"", j + 1)
1314
+ j += 2
1315
+ selfClosing = true
1316
+ break
1317
+ }
1318
+ if (!space) throw this.syntax("expected whitespace, \">\" or \"/>\"", j)
1319
+ const nameStart = j
1320
+ j = scanName(s, j, n)
1321
+ if (j === nameStart) throw this.syntax("invalid attribute name", j)
1322
+ if (j >= n) return -1
1323
+ const attribute = s.slice(nameStart, j)
1324
+ j = skipSpace(s, j, n)
1325
+ if (j >= n) return -1
1326
+ if (s.charCodeAt(j) !== EQUALS) throw this.syntax("expected \"=\"", j)
1327
+ j = skipSpace(s, j + 1, n)
1328
+ if (j >= n) return -1
1329
+ const quote = s.charCodeAt(j)
1330
+ if (quote !== DQUOTE && quote !== SQUOTE) throw this.syntax("expected a quoted attribute value", j)
1331
+ const close = s.indexOf(quote === DQUOTE ? "\"" : "'", j + 1)
1332
+ if (close === -1) {
1333
+ const lt = s.indexOf("<", j + 1)
1334
+ if (lt !== -1) throw this.syntax("\"<\" is not allowed in attribute values", lt)
1335
+ return -1
1336
+ }
1337
+ const value = this.attributeValue(s, j + 1, close)
1338
+ if (attributes === undefined) {
1339
+ shape = this.shapes.get(name)
1340
+ if (shape === undefined && this.shapes.size < maxShapes) {
1341
+ shape = []
1342
+ this.shapes.set(name, shape)
1343
+ }
1344
+ attributes = shape === undefined || shape === null || shape.length > maxFastAttributes ?
1345
+ Object.create(null) as Record<string, string> :
1346
+ new Attributes()
1347
+ } else if (attributes[attribute] !== undefined) {
1348
+ throw this.syntax(`duplicate attribute ${attribute}`, nameStart)
1349
+ }
1350
+ if (shape !== undefined && shape !== null && shape.length <= maxFastAttributes) {
1351
+ // Stored names are copied, as they outlive the chunk
1352
+ if (index === shape.length) shape.push((" " + attribute).slice(1))
1353
+ else if (shape[index] !== attribute) {
1354
+ this.shapes.set(name, null)
1355
+ shape = null
1356
+ }
1357
+ }
1358
+ index++
1359
+ attributes[attribute] = value
1360
+ j = close + 1
1361
+ if (j >= n) return -1
1362
+ }
1363
+ this.checkSize(i, j)
1364
+ if (this.stack.length >= this.maxDepth) {
1365
+ throw this.error("Limit", `element nesting exceeds maxDepth of ${this.maxDepth}`, this.base + i)
1366
+ }
1367
+ if (!selfClosing && this.openNameSize + name.length > this.maxTokenSize) {
1368
+ throw this.error("Limit", `open element names exceed maxTokenSize of ${this.maxTokenSize}`, this.base + i)
1369
+ }
1370
+ this.flushText()
1371
+ this.out.push({ _tag: "StartElement", name, attributes: attributes ?? emptyAttributes })
1372
+ if (selfClosing) {
1373
+ this.out.push({ _tag: "EndElement", name })
1374
+ if (this.stack.length === 0) this.state = EPILOG
1375
+ } else {
1376
+ this.stack.push(name)
1377
+ this.openNameSize += name.length
1378
+ this.state = CONTENT
1379
+ }
1380
+ return j
1381
+ }
1382
+
1383
+ private attributeValue(s: string, i: number, j: number): string {
1384
+ let reference = false
1385
+ let whitespace = false
1386
+ if (j - i < shortValue) {
1387
+ for (let k = i; k < j; k++) {
1388
+ const c = s.charCodeAt(k)
1389
+ if (c === LT) throw this.syntax("\"<\" is not allowed in attribute values", k)
1390
+ if (c === AMPERSAND) reference = true
1391
+ else if (c === TAB || c === LF || c === CR) whitespace = true
1392
+ }
1393
+ if (!reference && !whitespace) return s.slice(i, j)
1394
+ } else {
1395
+ // A regex search beats the loop above on long values
1396
+ const value = s.slice(i, j)
1397
+ const special = value.search(attributeSpecial)
1398
+ if (special === -1) return value
1399
+ const lt = value.indexOf("<", special)
1400
+ if (lt !== -1) throw this.syntax("\"<\" is not allowed in attribute values", i + lt)
1401
+ reference = value.indexOf("&", special) !== -1
1402
+ whitespace = !reference || attributeWhitespaceChar.test(value)
1403
+ }
1404
+ const raw = s.slice(i, j)
1405
+ return reference ? this.decodeText(raw, i, true, whitespace) : normalizeAttribute(raw)
1406
+ }
1407
+
1408
+ private endTag(s: string, i: number): number {
1409
+ const n = s.length
1410
+ const j = scanName(s, i + 2, n)
1411
+ if (j === i + 2) {
1412
+ if (j >= n) return -1
1413
+ throw this.syntax("invalid element name", j)
1414
+ }
1415
+ const k = skipSpace(s, j, n)
1416
+ if (k >= n) return -1
1417
+ if (s.charCodeAt(k) !== GT) throw this.syntax("expected \">\"", k)
1418
+ const open = this.stack.length > 0 ? this.stack[this.stack.length - 1] : undefined
1419
+ if (open === undefined) throw this.syntax("end tag without a start tag", i)
1420
+ if (j - i - 2 !== open.length || !s.startsWith(open, i + 2)) {
1421
+ throw this.syntax(`end tag </${s.slice(i + 2, j)}> does not match <${open}>`, i)
1422
+ }
1423
+ this.checkSize(i, k + 1)
1424
+ this.flushText()
1425
+ this.stack.pop()
1426
+ this.openNameSize -= open.length
1427
+ this.out.push({ _tag: "EndElement", name: open })
1428
+ if (this.stack.length === 0) this.state = EPILOG
1429
+ return k + 1
1430
+ }
1431
+
1432
+ private comment(s: string, i: number): number {
1433
+ const end = s.indexOf("-->", i + 4)
1434
+ if (end === -1) return -1
1435
+ const dashes = s.indexOf("--", i + 4)
1436
+ if (dashes < end) throw this.syntax("\"--\" is not allowed in comments", dashes)
1437
+ this.checkSize(i, end + 3)
1438
+ this.flushText()
1439
+ this.out.push({ _tag: "Comment", text: normalizeLines(s.slice(i + 4, end)) })
1440
+ return end + 3
1441
+ }
1442
+
1443
+ private processingInstruction(s: string, i: number): number {
1444
+ const end = s.indexOf("?>", i + 2)
1445
+ if (end === -1) return -1
1446
+ const t = scanName(s, i + 2, end)
1447
+ if (t === i + 2) throw this.syntax("invalid processing instruction target", i + 2)
1448
+ const target = s.slice(i + 2, t)
1449
+ if (isReservedTarget(target)) {
1450
+ if (target === "xml" && this.base + i === 0) return this.declaration(s, i, t, end)
1451
+ throw this.syntax(
1452
+ target === "xml" ?
1453
+ "the XML declaration is only allowed at the start of the document" :
1454
+ `processing instruction target ${target} is reserved`,
1455
+ i
1456
+ )
1457
+ }
1458
+ let data = ""
1459
+ if (t < end) {
1460
+ if (!isSpace(s.charCodeAt(t))) throw this.syntax("expected whitespace after the target", t)
1461
+ data = normalizeLines(s.slice(skipSpace(s, t, end), end))
1462
+ }
1463
+ this.checkSize(i, end + 2)
1464
+ this.flushText()
1465
+ this.out.push({ _tag: "ProcessingInstruction", target, data })
1466
+ return end + 2
1467
+ }
1468
+
1469
+ private declaration(s: string, i: number, t: number, end: number): number {
1470
+ this.checkSize(i, end + 2)
1471
+ const match = declarationPattern.exec(s.slice(t, end))
1472
+ if (match === null) throw this.syntax("invalid XML declaration", i)
1473
+ const encoding = match[3] ?? match[4]
1474
+ const standalone = match[5] ?? match[6]
1475
+ if (this.bytes && encoding !== undefined && !isUtf8(encoding)) {
1476
+ throw this.error(
1477
+ "Unsupported",
1478
+ `encoding ${encoding} is not supported for byte input, decode the bytes to text first`,
1479
+ this.base + i
1480
+ )
1481
+ }
1482
+ this.ascii = this.bytes && encoding?.toLowerCase() === "us-ascii"
1483
+ const event: { -readonly [K in keyof Declaration]: Declaration[K] } = {
1484
+ _tag: "Declaration",
1485
+ version: match[1] ?? match[2]
1486
+ }
1487
+ if (encoding !== undefined) event.encoding = encoding
1488
+ if (standalone !== undefined) event.standalone = standalone === "yes"
1489
+ this.out.push(event)
1490
+ return end + 2
1491
+ }
1492
+
1493
+ private cdata(s: string, i: number): number {
1494
+ const end = s.indexOf("]]>", i + 9)
1495
+ if (end === -1) return -1
1496
+ if (this.state !== CONTENT) throw this.syntax("CDATA sections are only allowed inside the root element", i)
1497
+ this.addText(i, end + 3 - i)
1498
+ this.text += normalizeLines(s.slice(i + 9, end))
1499
+ return end + 3
1500
+ }
1501
+
1502
+ private doctypeDeclaration(s: string, i: number): number {
1503
+ if (this.state !== PROLOG || this.doctype) {
1504
+ throw this.syntax("a DOCTYPE is only allowed once, before the root element", i)
1505
+ }
1506
+ const scanner = new Scanner()
1507
+ scanner.reset(S_DOCTYPE)
1508
+ const end = scanner.scan(s, i + 9)
1509
+ if (end === -1) return -1
1510
+ this.checkSize(i, end)
1511
+ this.doctype = true
1512
+ let j = this.space(s, i + 9, end)
1513
+ const nameEnd = this.name(s, j, end)
1514
+ const event: { -readonly [K in keyof Doctype]: Doctype[K] } = { _tag: "Doctype", name: s.slice(j, nameEnd) }
1515
+ j = skipSpace(s, nameEnd, end)
1516
+ if (j > nameEnd && (s.startsWith("PUBLIC", j) || s.startsWith("SYSTEM", j))) {
1517
+ if (s.charCodeAt(j) === 80) {
1518
+ // Whitespace in public identifiers is normalized for matching
1519
+ event.publicId = this.publicLiteral(s, this.space(s, j + 6, end), end).replace(publicIdWhitespace, " ").trim()
1520
+ j = this.literalEnd
1521
+ }
1522
+ event.systemId = normalizeLines(
1523
+ this.literal(s, this.space(s, j + (event.publicId === undefined ? 6 : 0), end), end)
1524
+ )
1525
+ j = skipSpace(s, this.literalEnd, end)
1526
+ }
1527
+ if (s.charCodeAt(j) === LBRACKET) {
1528
+ // The scanner skips the internal subset, whose declarations are not
1529
+ // checked, and ends the token early only at malformed markup
1530
+ if (scanner.state !== S_AFTER_SUBSET) throw this.syntax("invalid markup in the internal subset", end)
1531
+ j = skipSpace(s, s.lastIndexOf("]", end - 1) + 1, end)
1532
+ }
1533
+ if (j !== end - 1 || s.charCodeAt(j) !== GT) throw this.syntax("invalid DOCTYPE", j)
1534
+ this.out.push(event)
1535
+ return end
1536
+ }
1537
+
1538
+ // Skips the whitespace that is required at `i`
1539
+ private space(s: string, i: number, end: number): number {
1540
+ if (i >= end || !isSpace(s.charCodeAt(i))) throw this.syntax("expected whitespace", i)
1541
+ return skipSpace(s, i, end)
1542
+ }
1543
+
1544
+ // Returns the end of the name that is required at `i`
1545
+ private name(s: string, i: number, end: number): number {
1546
+ const nameEnd = scanName(s, i, end)
1547
+ if (nameEnd === i) throw this.syntax("expected a name", i)
1548
+ return nameEnd
1549
+ }
1550
+
1551
+ // Reads the quoted literal at `i`, and sets `literalEnd` to the index after it
1552
+ private literal(s: string, i: number, end: number): string {
1553
+ const quote = s.charCodeAt(i)
1554
+ if (quote !== DQUOTE && quote !== SQUOTE) throw this.syntax("expected a quoted literal", i)
1555
+ const close = s.indexOf(quote === DQUOTE ? "\"" : "'", i + 1)
1556
+ // Unreachable while the scanner ends a DOCTYPE only after its literals close
1557
+ if (close === -1 || close >= end) throw this.syntax("unterminated literal", i)
1558
+ this.literalEnd = close + 1
1559
+ return s.slice(i + 1, close)
1560
+ }
1561
+
1562
+ private publicLiteral(s: string, i: number, end: number): string {
1563
+ const literal = this.literal(s, i, end)
1564
+ if (!pubidPattern.test(literal)) throw this.syntax("invalid public identifier", i)
1565
+ return literal
1566
+ }
1567
+ }
1568
+
1569
+ const indexOrEnd = (s: string, search: string, from: number): number => {
1570
+ const i = s.indexOf(search, from)
1571
+ return i === -1 ? s.length : i
1572
+ }
1573
+
1574
+ class TextInput implements Machine<string, Event> {
1575
+ private readonly parser: Parser
1576
+ // A high surrogate at the end of a chunk, which pairs with the next chunk
1577
+ private surrogate = ""
1578
+
1579
+ constructor(parser: Parser) {
1580
+ this.parser = parser
1581
+ }
1582
+
1583
+ get out(): Array<Event> {
1584
+ return this.parser.out
1585
+ }
1586
+ set out(out: Array<Event>) {
1587
+ this.parser.out = out
1588
+ }
1589
+
1590
+ push(chunk: string): void {
1591
+ if (this.surrogate !== "") {
1592
+ chunk = this.surrogate + chunk
1593
+ this.surrogate = ""
1594
+ }
1595
+ const last = chunk.charCodeAt(chunk.length - 1)
1596
+ if (last >= 0xD800 && last <= 0xDBFF) {
1597
+ this.surrogate = chunk.slice(-1)
1598
+ chunk = chunk.slice(0, -1)
1599
+ }
1600
+ this.parser.feed(chunk)
1601
+ }
1602
+
1603
+ end(): void {
1604
+ // An unpaired high surrogate fails as an invalid character
1605
+ this.parser.feed(this.surrogate)
1606
+ this.parser.end()
1607
+ }
1608
+ }
1609
+
1610
+ const utf8Length = (lead: number): number => lead >= 0xF0 ? 4 : lead >= 0xE0 ? 3 : lead >= 0xC0 ? 2 : 1
1611
+
1612
+ // Returns the length of the valid UTF-8 prefix of `bytes`
1613
+ const validUtf8 = (bytes: Uint8Array): number => {
1614
+ let i = 0
1615
+ while (i < bytes.length) {
1616
+ const lead = bytes[i]
1617
+ if (lead < 0x80) {
1618
+ i++
1619
+ continue
1620
+ }
1621
+ const length = lead >= 0xC2 && lead <= 0xF4 ? utf8Length(lead) : 0
1622
+ if (length === 0 || i + length > bytes.length) return i
1623
+ let code = lead & (0xFF >> (length + 1))
1624
+ for (let k = 1; k < length; k++) {
1625
+ const c = bytes[i + k]
1626
+ if ((c & 0xC0) !== 0x80) return i
1627
+ code = (code << 6) | (c & 0x3F)
1628
+ }
1629
+ const min = length === 2 ? 0x80 : length === 3 ? 0x800 : 0x10000
1630
+ if (code < min || code > 0x10FFFF || (code >= 0xD800 && code <= 0xDFFF)) return i
1631
+ i += length
1632
+ }
1633
+ return i
1634
+ }
1635
+
1636
+ const utf8Decoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true })
1637
+
1638
+ // Decodes UTF-8 without streaming state, so that the position of invalid bytes
1639
+ // is known: an incomplete sequence at the end of a chunk is carried over.
1640
+ class Utf8Input implements Machine<Uint8Array, Event> {
1641
+ private readonly parser: Parser
1642
+ private carry: Uint8Array | undefined
1643
+ private started = false
1644
+
1645
+ constructor(parser: Parser) {
1646
+ this.parser = parser
1647
+ }
1648
+
1649
+ get out(): Array<Event> {
1650
+ return this.parser.out
1651
+ }
1652
+ set out(out: Array<Event>) {
1653
+ this.parser.out = out
1654
+ }
1655
+
1656
+ push(chunk: Uint8Array): void {
1657
+ if (!this.started && chunk.length > 0) {
1658
+ const first = this.carry === undefined ? chunk[0] : this.carry[0]
1659
+ const second = this.carry === undefined ? chunk[1] : chunk[0]
1660
+ if ((first === 0xFE && second === 0xFF) || (first === 0xFF && second === 0xFE)) {
1661
+ throw this.parser.error(
1662
+ "Unsupported",
1663
+ "UTF-16 is not supported for byte input, decode the bytes to text first",
1664
+ 0
1665
+ )
1666
+ }
1667
+ // Keep a lone BOM prefix pending in the UTF-8 carry below
1668
+ this.started = second !== undefined || (first !== 0xFE && first !== 0xFF)
1669
+ }
1670
+ let start = 0
1671
+ if (this.carry !== undefined) {
1672
+ const need = utf8Length(this.carry[0]) - this.carry.length
1673
+ const head = new Uint8Array(this.carry.length + Math.min(need, chunk.length))
1674
+ head.set(this.carry)
1675
+ head.set(chunk.subarray(0, need), this.carry.length)
1676
+ if (chunk.length < need) {
1677
+ this.carry = head
1678
+ return
1679
+ }
1680
+ this.carry = undefined
1681
+ this.decode(head)
1682
+ start = need
1683
+ }
1684
+ const n = chunk.length
1685
+ let end = n
1686
+ for (let k = 1; k <= 3 && n - k >= start; k++) {
1687
+ const b = chunk[n - k]
1688
+ if ((b & 0xC0) === 0x80) continue
1689
+ if (b >= 0xC0 && k < utf8Length(b)) end = n - k
1690
+ break
1691
+ }
1692
+ if (end < n) this.carry = chunk.slice(end)
1693
+ if (end > start) this.decode(start === 0 && end === n ? chunk : chunk.subarray(start, end))
1694
+ }
1695
+
1696
+ end(): void {
1697
+ // The carried bytes may also be an invalid sequence, such as a single 0xFF
1698
+ if (this.carry !== undefined) {
1699
+ this.parser.feed("", true)
1700
+ throw this.parser.error("Syntax", "invalid UTF-8", this.parser.received)
1701
+ }
1702
+ this.parser.end()
1703
+ }
1704
+
1705
+ private decode(bytes: Uint8Array): void {
1706
+ let text: string
1707
+ try {
1708
+ text = utf8Decoder.decode(bytes)
1709
+ } catch {
1710
+ this.parser.feed(utf8Decoder.decode(bytes.subarray(0, validUtf8(bytes))), true)
1711
+ throw this.parser.error("Syntax", "invalid UTF-8", this.parser.received)
1712
+ }
1713
+ this.parser.feed(text)
1714
+ }
1715
+ }
1716
+
1717
+ interface MutableElement {
1718
+ readonly name: string
1719
+ readonly attributes: Readonly<Record<string, string>>
1720
+ readonly children: Array<MutableElement | string>
1721
+ }
1722
+
1723
+ class Collector implements Machine<Event, Element> {
1724
+ out: Array<Element> = []
1725
+ private depth = 0
1726
+ // Number of open elements, from the root, that match the path
1727
+ private matched = 0
1728
+ // The element being collected and its open descendants
1729
+ private readonly stack: Array<MutableElement> = []
1730
+ private size = 0
1731
+ private readonly path: ReadonlyArray<string>
1732
+ private readonly maxElementSize: number
1733
+
1734
+ constructor(path: ReadonlyArray<string>, maxElementSize: number) {
1735
+ this.path = path
1736
+ this.maxElementSize = maxElementSize
1737
+ }
1738
+
1739
+ push(event: Event): void {
1740
+ switch (event._tag) {
1741
+ case "StartElement": {
1742
+ const depth = this.depth++
1743
+ if (this.stack.length === 0) {
1744
+ const segment = this.path[depth]
1745
+ if (this.matched !== depth || (segment !== "*" && segment !== event.name)) return
1746
+ if (++this.matched < this.path.length) return
1747
+ this.size = 0
1748
+ }
1749
+ const element: MutableElement = { name: event.name, attributes: event.attributes, children: [] }
1750
+ if (this.stack.length > 0) this.stack[this.stack.length - 1].children.push(element)
1751
+ this.stack.push(element)
1752
+ let size = event.name.length
1753
+ for (const key in event.attributes) size += key.length + event.attributes[key].length
1754
+ this.grow(size)
1755
+ return
1756
+ }
1757
+ case "EndElement": {
1758
+ if (this.depth === 0) throw invalidEvent(`end tag </${event.name}> without a start tag`)
1759
+ if (this.stack.length > 0) {
1760
+ const element = this.stack.pop()!
1761
+ if (this.stack.length === 0) this.out.push(element)
1762
+ }
1763
+ if (this.matched === this.depth) this.matched--
1764
+ this.depth--
1765
+ return
1766
+ }
1767
+ case "Text": {
1768
+ if (this.stack.length === 0 || event.text.length === 0) return
1769
+ this.grow(event.text.length)
1770
+ const children = this.stack[this.stack.length - 1].children
1771
+ const last = children.length - 1
1772
+ if (last >= 0 && typeof children[last] === "string") children[last] += event.text
1773
+ else children.push(event.text)
1774
+ return
1775
+ }
1776
+ }
1777
+ }
1778
+
1779
+ end(): void {
1780
+ if (this.depth > 0) throw invalidEvent("events ended inside an element")
1781
+ }
1782
+
1783
+ private grow(size: number): void {
1784
+ this.size += size
1785
+ if (this.size > this.maxElementSize) {
1786
+ throw positionless("Limit", `element <${this.stack[0].name}> exceeds maxElementSize of ${this.maxElementSize}`)
1787
+ }
1788
+ }
1789
+ }
1790
+
1791
+ // JavaScriptCore gives every Error its own source `line` and `column`, which
1792
+ // would pass for an XML position, so errors without one set both to undefined
1793
+ const positionless = (kind: XmlError["kind"], message: string) =>
1794
+ new XmlError({ kind, message, line: undefined, column: undefined })
1795
+
1796
+ const invalidEvent = (message: string) => positionless("InvalidEvent", message)
1797
+
1798
+ const textSpecial = /[&<>\r]/
1799
+ const attributeSpecials = /[&<"\t\n\r]/
1800
+
1801
+ // The regex finds the first special character, which is fast when there is
1802
+ // none; the rest is copied in runs between escapes. Invalid characters are
1803
+ // kept, so that the writer can check them in the output.
1804
+ const escapeText = (s: string): string => {
1805
+ const first = s.search(textSpecial)
1806
+ if (first === -1) return s
1807
+ let out = ""
1808
+ let last = 0
1809
+ for (let i = first; i < s.length; i++) {
1810
+ const c = s.charCodeAt(i)
1811
+ const escaped = c === AMPERSAND ? "&amp;" : c === LT ? "&lt;" : c === GT ? "&gt;" : c === CR ? "&#13;" : undefined
1812
+ if (escaped !== undefined) {
1813
+ out += s.slice(last, i) + escaped
1814
+ last = i + 1
1815
+ }
1816
+ }
1817
+ return out + s.slice(last)
1818
+ }
1819
+
1820
+ const escapeAttribute = (s: string): string => {
1821
+ const first = s.search(attributeSpecials)
1822
+ if (first === -1) return s
1823
+ let out = ""
1824
+ let last = 0
1825
+ for (let i = first; i < s.length; i++) {
1826
+ const c = s.charCodeAt(i)
1827
+ const escaped = c === AMPERSAND ?
1828
+ "&amp;" :
1829
+ c === LT ?
1830
+ "&lt;" :
1831
+ c === DQUOTE ?
1832
+ "&quot;" :
1833
+ c === TAB ?
1834
+ "&#9;" :
1835
+ c === LF ?
1836
+ "&#10;" :
1837
+ c === CR ?
1838
+ "&#13;" :
1839
+ undefined
1840
+ if (escaped !== undefined) {
1841
+ out += s.slice(last, i) + escaped
1842
+ last = i + 1
1843
+ }
1844
+ }
1845
+ return out + s.slice(last)
1846
+ }
1847
+
1848
+ const checkChars = (what: string, s: string): void => {
1849
+ const invalid = searchInvalid(s)
1850
+ if (invalid !== -1) {
1851
+ const code = s.codePointAt(invalid)!.toString(16).toUpperCase().padStart(4, "0")
1852
+ throw invalidEvent(`${what} contains the invalid character U+${code}`)
1853
+ }
1854
+ }
1855
+
1856
+ const checkName = (what: string, name: string): void => {
1857
+ if (typeof name !== "string" || !isName(name)) throw invalidEvent(`invalid ${what} ${JSON.stringify(name)}`)
1858
+ }
1859
+
1860
+ const isWhitespace = (s: string): boolean => {
1861
+ for (let i = 0; i < s.length; i++) {
1862
+ if (!isSpace(s.charCodeAt(i))) return false
1863
+ }
1864
+ return true
1865
+ }
1866
+
1867
+ const NOTHING_WRITTEN = 3
1868
+
1869
+ class Writer implements Machine<Event, string> {
1870
+ out: Array<string> = []
1871
+ private readonly stack: Array<string> = []
1872
+ private state = NOTHING_WRITTEN
1873
+ private doctype = false
1874
+ private readonly bytes: boolean
1875
+ // Element and attribute names already checked, which repeat in most
1876
+ // documents. Cleared when full, so that it stays small.
1877
+ private readonly names = new Set<string>()
1878
+
1879
+ constructor(bytes: boolean) {
1880
+ this.bytes = bytes
1881
+ }
1882
+
1883
+ private checkName(what: string, name: string): void {
1884
+ if (!this.isName(name)) checkName(what, name)
1885
+ }
1886
+
1887
+ private isName(name: string): boolean {
1888
+ if (this.names.has(name)) return true
1889
+ if (typeof name !== "string" || !isName(name)) return false
1890
+ if (this.names.size >= 1024) this.names.clear()
1891
+ this.names.add(name)
1892
+ return true
1893
+ }
1894
+
1895
+ // Checks attributes one by one, in order, after a batched check has failed
1896
+ private checkAttributes(attributes: Readonly<Record<string, string>>): void {
1897
+ for (const name in attributes) {
1898
+ if (!Object.hasOwn(attributes, name)) continue
1899
+ const value = attributes[name]
1900
+ this.checkName("attribute name", name)
1901
+ if (typeof value !== "string") throw invalidEvent(`attribute ${name} must be a string`)
1902
+ checkChars(`attribute ${name}`, value)
1903
+ }
1904
+ }
1905
+
1906
+ push(event: Event): void {
1907
+ const text = this.write(event)
1908
+ if (text.length > 0) {
1909
+ const out = this.out
1910
+ if (out.length > 0) out[0] += text
1911
+ else out.push(text)
1912
+ }
1913
+ }
1914
+
1915
+ end(): void {
1916
+ if (this.stack.length > 0) throw invalidEvent(`unclosed element <${this.stack[this.stack.length - 1]}>`)
1917
+ if (this.state !== EPILOG) throw invalidEvent("no root element")
1918
+ }
1919
+
1920
+ private write(event: Event): string {
1921
+ if (event._tag === "EndElement") {
1922
+ const open = this.stack.length > 0 ? this.stack[this.stack.length - 1] : undefined
1923
+ if (open === undefined || event.name !== open) {
1924
+ // Only valid names are written into messages
1925
+ checkName("element name", event.name)
1926
+ throw invalidEvent(
1927
+ open === undefined
1928
+ ? `end tag </${event.name}> without a start tag`
1929
+ : `end tag </${event.name}> does not match <${open}>`
1930
+ )
1931
+ }
1932
+ this.stack.pop()
1933
+ if (this.stack.length === 0) this.state = EPILOG
1934
+ return `</${open}>`
1935
+ }
1936
+ switch (event._tag) {
1937
+ case "StartElement": {
1938
+ this.checkName("element name", event.name)
1939
+ if (this.state === EPILOG) throw invalidEvent(`second root element <${event.name}>`)
1940
+ let tag = "<" + event.name
1941
+ let valid = true
1942
+ for (const name in event.attributes) {
1943
+ if (!Object.hasOwn(event.attributes, name)) continue
1944
+ const value = event.attributes[name]
1945
+ if (typeof value !== "string" || !this.isName(name)) {
1946
+ valid = false
1947
+ break
1948
+ }
1949
+ tag += ` ${name}="${escapeAttribute(value)}"`
1950
+ }
1951
+ // Escaping keeps invalid characters, so one search of the tag checks
1952
+ // every value; the first error is then found in attribute order
1953
+ if (!valid || (tag.length > event.name.length + 1 && searchInvalid(tag) !== -1)) {
1954
+ this.checkAttributes(event.attributes)
1955
+ }
1956
+ this.stack.push(event.name)
1957
+ this.state = CONTENT
1958
+ return tag + ">"
1959
+ }
1960
+ case "Text": {
1961
+ if (this.state !== CONTENT) {
1962
+ checkChars("text", event.text)
1963
+ if (!isWhitespace(event.text)) throw invalidEvent("text outside the root element must be whitespace")
1964
+ if (this.state === NOTHING_WRITTEN && event.text.length > 0) this.state = PROLOG
1965
+ return event.text
1966
+ }
1967
+ checkChars("text", event.text)
1968
+ return escapeText(event.text)
1969
+ }
1970
+ case "Comment": {
1971
+ checkChars("comment", event.text)
1972
+ if (event.text.includes("--") || event.text.endsWith("-")) {
1973
+ throw invalidEvent("comments cannot contain \"--\" or end with \"-\"")
1974
+ }
1975
+ if (this.state === NOTHING_WRITTEN) this.state = PROLOG
1976
+ return `<!--${event.text}-->`
1977
+ }
1978
+ case "ProcessingInstruction": {
1979
+ checkName("processing instruction target", event.target)
1980
+ if (isReservedTarget(event.target)) {
1981
+ throw invalidEvent(`processing instruction target ${event.target} is reserved`)
1982
+ }
1983
+ checkChars("processing instruction", event.data)
1984
+ if (event.data.includes("?>")) throw invalidEvent("processing instruction data cannot contain \"?>\"")
1985
+ if (this.state === NOTHING_WRITTEN) this.state = PROLOG
1986
+ return `<?${event.target}${event.data === "" ? "" : " " + event.data}?>`
1987
+ }
1988
+ case "Declaration": {
1989
+ if (this.state !== NOTHING_WRITTEN) throw invalidEvent("the XML declaration must be the first event")
1990
+ if (!versionPattern.test(event.version)) {
1991
+ throw invalidEvent(`invalid XML version ${JSON.stringify(event.version)}`)
1992
+ }
1993
+ let declaration = `<?xml version="${event.version}"`
1994
+ if (event.encoding !== undefined) {
1995
+ if (!encodingPattern.test(event.encoding)) {
1996
+ throw invalidEvent(`invalid encoding name ${JSON.stringify(event.encoding)}`)
1997
+ }
1998
+ if (this.bytes && event.encoding.toLowerCase() !== "utf-8") {
1999
+ throw invalidEvent(`encoding ${event.encoding} cannot be declared for UTF-8 output`)
2000
+ }
2001
+ declaration += ` encoding="${event.encoding}"`
2002
+ }
2003
+ if (event.standalone !== undefined) declaration += ` standalone="${event.standalone ? "yes" : "no"}"`
2004
+ this.state = PROLOG
2005
+ return declaration + "?>"
2006
+ }
2007
+ case "Doctype": {
2008
+ if (this.state === CONTENT || this.state === EPILOG || this.doctype) {
2009
+ throw invalidEvent("a DOCTYPE must appear once, before the root element")
2010
+ }
2011
+ checkName("DOCTYPE name", event.name)
2012
+ let doctype = `<!DOCTYPE ${event.name}`
2013
+ if (event.publicId !== undefined) {
2014
+ if (event.systemId === undefined) {
2015
+ throw invalidEvent("a DOCTYPE with a public identifier needs a system identifier")
2016
+ }
2017
+ if (!pubidPattern.test(event.publicId)) {
2018
+ throw invalidEvent(`invalid public identifier ${JSON.stringify(event.publicId)}`)
2019
+ }
2020
+ doctype += ` PUBLIC "${event.publicId}"`
2021
+ }
2022
+ if (event.systemId !== undefined) {
2023
+ checkChars("system identifier", event.systemId)
2024
+ const hasDouble = event.systemId.includes("\"")
2025
+ if (hasDouble && event.systemId.includes("'")) {
2026
+ throw invalidEvent("a system identifier cannot contain both quote characters")
2027
+ }
2028
+ if (event.publicId === undefined) doctype += " SYSTEM"
2029
+ doctype += hasDouble ? ` '${event.systemId}'` : ` "${event.systemId}"`
2030
+ }
2031
+ this.doctype = true
2032
+ this.state = PROLOG
2033
+ return doctype + ">"
2034
+ }
2035
+ }
2036
+ }
2037
+ }