@pithy-sh/core 0.1.2 → 0.1.4

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 (393) hide show
  1. package/dist/address/address.d.ts +57 -0
  2. package/dist/address/address.d.ts.map +1 -0
  3. package/dist/address/address.js +71 -0
  4. package/dist/audit/auditEvent.d.ts +89 -0
  5. package/dist/audit/auditEvent.d.ts.map +1 -0
  6. package/dist/audit/auditEvent.js +69 -0
  7. package/dist/audit/recorder.d.ts +18 -0
  8. package/dist/audit/recorder.d.ts.map +1 -0
  9. package/dist/audit/recorder.js +8 -0
  10. package/dist/capability/bindings.d.ts +62 -0
  11. package/dist/capability/bindings.d.ts.map +1 -0
  12. package/dist/capability/bindings.js +97 -0
  13. package/dist/capability/capability.d.ts +501 -0
  14. package/dist/capability/capability.d.ts.map +1 -0
  15. package/dist/capability/capability.js +16 -0
  16. package/dist/capability/client.d.ts +70 -0
  17. package/dist/capability/client.d.ts.map +1 -0
  18. package/dist/capability/client.js +86 -0
  19. package/dist/capability/compose.d.ts +25 -0
  20. package/dist/capability/compose.d.ts.map +1 -0
  21. package/dist/capability/compose.js +54 -0
  22. package/dist/capability/composition.d.ts +26 -0
  23. package/dist/capability/composition.d.ts.map +1 -0
  24. package/dist/capability/composition.js +84 -0
  25. package/dist/capability/config.d.ts +7 -0
  26. package/dist/capability/config.d.ts.map +1 -0
  27. package/dist/capability/config.js +14 -0
  28. package/dist/capability/devSecret.d.ts +32 -0
  29. package/dist/capability/devSecret.d.ts.map +1 -0
  30. package/dist/capability/devSecret.js +28 -0
  31. package/dist/capability/manifest.d.ts +298 -0
  32. package/dist/capability/manifest.d.ts.map +1 -0
  33. package/dist/capability/manifest.js +356 -0
  34. package/dist/capability/secretOrigin.d.ts +121 -0
  35. package/dist/capability/secretOrigin.d.ts.map +1 -0
  36. package/dist/capability/secretOrigin.js +134 -0
  37. package/dist/capability/settings.d.ts +119 -0
  38. package/dist/capability/settings.d.ts.map +1 -0
  39. package/dist/capability/settings.js +66 -0
  40. package/dist/capability/validateBindings.d.ts +4 -0
  41. package/dist/capability/validateBindings.d.ts.map +1 -0
  42. package/dist/capability/validateBindings.js +34 -0
  43. package/dist/capability/vanishingKey.d.ts +31 -0
  44. package/dist/capability/vanishingKey.d.ts.map +1 -0
  45. package/dist/capability/vanishingKey.js +79 -0
  46. package/dist/controlPlane/audit/actions.d.ts +70 -0
  47. package/dist/controlPlane/audit/actions.d.ts.map +1 -0
  48. package/dist/controlPlane/audit/actions.js +76 -0
  49. package/dist/controlPlane/capability.d.ts +47 -0
  50. package/dist/controlPlane/capability.d.ts.map +1 -0
  51. package/dist/controlPlane/capability.js +138 -0
  52. package/dist/controlPlane/config/config.d.ts +19 -0
  53. package/dist/controlPlane/config/config.d.ts.map +1 -0
  54. package/dist/controlPlane/config/config.js +85 -0
  55. package/dist/controlPlane/context.d.ts +27 -0
  56. package/dist/controlPlane/context.d.ts.map +1 -0
  57. package/dist/controlPlane/context.js +29 -0
  58. package/dist/controlPlane/data/connection.d.ts +79 -0
  59. package/dist/controlPlane/data/connection.d.ts.map +1 -0
  60. package/dist/controlPlane/data/connection.js +55 -0
  61. package/dist/controlPlane/data/keyLifecycle.d.ts +62 -0
  62. package/dist/controlPlane/data/keyLifecycle.d.ts.map +1 -0
  63. package/dist/controlPlane/data/keyLifecycle.js +126 -0
  64. package/dist/controlPlane/data/replay.d.ts +18 -0
  65. package/dist/controlPlane/data/replay.d.ts.map +1 -0
  66. package/dist/controlPlane/data/replay.js +20 -0
  67. package/dist/controlPlane/data/tables.d.ts +34 -0
  68. package/dist/controlPlane/data/tables.d.ts.map +1 -0
  69. package/dist/controlPlane/data/tables.js +37 -0
  70. package/dist/controlPlane/discovery/adminRoute.d.ts +313 -0
  71. package/dist/controlPlane/discovery/adminRoute.d.ts.map +1 -0
  72. package/dist/controlPlane/discovery/adminRoute.js +136 -0
  73. package/dist/controlPlane/discovery/configuration.d.ts +108 -0
  74. package/dist/controlPlane/discovery/configuration.d.ts.map +1 -0
  75. package/dist/controlPlane/discovery/configuration.js +187 -0
  76. package/dist/controlPlane/discovery/drift.d.ts +64 -0
  77. package/dist/controlPlane/discovery/drift.d.ts.map +1 -0
  78. package/dist/controlPlane/discovery/drift.js +58 -0
  79. package/dist/controlPlane/discovery/health.d.ts +99 -0
  80. package/dist/controlPlane/discovery/health.d.ts.map +1 -0
  81. package/dist/controlPlane/discovery/health.js +151 -0
  82. package/dist/controlPlane/discovery/healthSummary.d.ts +236 -0
  83. package/dist/controlPlane/discovery/healthSummary.d.ts.map +1 -0
  84. package/dist/controlPlane/discovery/healthSummary.js +278 -0
  85. package/dist/controlPlane/error/errors.d.ts +67 -0
  86. package/dist/controlPlane/error/errors.d.ts.map +1 -0
  87. package/dist/controlPlane/error/errors.js +79 -0
  88. package/dist/controlPlane/http/cors.d.ts +112 -0
  89. package/dist/controlPlane/http/cors.d.ts.map +1 -0
  90. package/dist/controlPlane/http/cors.js +192 -0
  91. package/dist/controlPlane/http/guard.d.ts +77 -0
  92. package/dist/controlPlane/http/guard.d.ts.map +1 -0
  93. package/dist/controlPlane/http/guard.js +142 -0
  94. package/dist/controlPlane/http/handlers.d.ts +179 -0
  95. package/dist/controlPlane/http/handlers.d.ts.map +1 -0
  96. package/dist/controlPlane/http/handlers.js +245 -0
  97. package/dist/controlPlane/http/responses.d.ts +99 -0
  98. package/dist/controlPlane/http/responses.d.ts.map +1 -0
  99. package/dist/controlPlane/http/responses.js +63 -0
  100. package/dist/controlPlane/http/routes.d.ts +40 -0
  101. package/dist/controlPlane/http/routes.d.ts.map +1 -0
  102. package/dist/controlPlane/http/routes.js +83 -0
  103. package/dist/controlPlane/http/schemas.d.ts +39 -0
  104. package/dist/controlPlane/http/schemas.d.ts.map +1 -0
  105. package/dist/controlPlane/http/schemas.js +31 -0
  106. package/dist/controlPlane/http/verify.d.ts +84 -0
  107. package/dist/controlPlane/http/verify.d.ts.map +1 -0
  108. package/dist/controlPlane/http/verify.js +65 -0
  109. package/dist/controlPlane/migrations/0001_init.d.ts +51 -0
  110. package/dist/controlPlane/migrations/0001_init.d.ts.map +1 -0
  111. package/dist/controlPlane/migrations/0001_init.js +65 -0
  112. package/dist/controlPlane/replay/d1Guard.d.ts +29 -0
  113. package/dist/controlPlane/replay/d1Guard.d.ts.map +1 -0
  114. package/dist/controlPlane/replay/d1Guard.js +39 -0
  115. package/dist/controlPlane/replay/guard.d.ts +52 -0
  116. package/dist/controlPlane/replay/guard.d.ts.map +1 -0
  117. package/dist/controlPlane/replay/guard.js +0 -0
  118. package/dist/controlPlane/replay/kvGuard.d.ts +99 -0
  119. package/dist/controlPlane/replay/kvGuard.d.ts.map +1 -0
  120. package/dist/controlPlane/replay/kvGuard.js +101 -0
  121. package/dist/controlPlane/scope/scope.d.ts +68 -0
  122. package/dist/controlPlane/scope/scope.d.ts.map +1 -0
  123. package/dist/controlPlane/scope/scope.js +63 -0
  124. package/dist/controlPlane/token/base64url.d.ts +10 -0
  125. package/dist/controlPlane/token/base64url.d.ts.map +1 -0
  126. package/dist/controlPlane/token/base64url.js +48 -0
  127. package/dist/controlPlane/token/claims.d.ts +83 -0
  128. package/dist/controlPlane/token/claims.d.ts.map +1 -0
  129. package/dist/controlPlane/token/claims.js +86 -0
  130. package/dist/controlPlane/token/digest.d.ts +44 -0
  131. package/dist/controlPlane/token/digest.d.ts.map +1 -0
  132. package/dist/controlPlane/token/digest.js +56 -0
  133. package/dist/controlPlane/token/jws.d.ts +52 -0
  134. package/dist/controlPlane/token/jws.d.ts.map +1 -0
  135. package/dist/controlPlane/token/jws.js +65 -0
  136. package/dist/controlPlane/token/mint.d.ts +56 -0
  137. package/dist/controlPlane/token/mint.d.ts.map +1 -0
  138. package/dist/controlPlane/token/mint.js +55 -0
  139. package/dist/controlPlane/wire.d.ts +122 -0
  140. package/dist/controlPlane/wire.d.ts.map +1 -0
  141. package/dist/controlPlane/wire.js +123 -0
  142. package/dist/createBackend.d.ts +58 -0
  143. package/dist/createBackend.d.ts.map +1 -0
  144. package/dist/createBackend.js +170 -0
  145. package/dist/createEntrypoint.d.ts +53 -0
  146. package/dist/createEntrypoint.d.ts.map +1 -0
  147. package/dist/createEntrypoint.js +52 -0
  148. package/dist/data/boundParameters.d.ts +83 -0
  149. package/dist/data/boundParameters.d.ts.map +1 -0
  150. package/dist/data/boundParameters.js +162 -0
  151. package/dist/data/codecs.d.ts +34 -0
  152. package/dist/data/codecs.d.ts.map +1 -0
  153. package/dist/data/codecs.js +135 -0
  154. package/dist/data/cursor.d.ts +81 -0
  155. package/dist/data/cursor.d.ts.map +1 -0
  156. package/dist/data/cursor.js +104 -0
  157. package/dist/data/databases.d.ts +55 -0
  158. package/dist/data/databases.d.ts.map +1 -0
  159. package/dist/data/databases.js +32 -0
  160. package/dist/data/db.d.ts +42 -0
  161. package/dist/data/db.d.ts.map +1 -0
  162. package/dist/data/db.js +24 -0
  163. package/dist/data/withD1Retry.d.ts +91 -0
  164. package/dist/data/withD1Retry.d.ts.map +1 -0
  165. package/dist/data/withD1Retry.js +152 -0
  166. package/dist/entitlement/entitlement.d.ts +118 -0
  167. package/dist/entitlement/entitlement.d.ts.map +1 -0
  168. package/dist/entitlement/entitlement.js +59 -0
  169. package/dist/entitlement/gateScan.d.ts +26 -0
  170. package/dist/entitlement/gateScan.d.ts.map +1 -0
  171. package/dist/entitlement/gateScan.js +96 -0
  172. package/dist/entitlement/require.d.ts +12 -0
  173. package/dist/entitlement/require.d.ts.map +1 -0
  174. package/dist/entitlement/require.js +123 -0
  175. package/dist/env/ambient.d.ts +52 -0
  176. package/dist/env/ambient.d.ts.map +1 -0
  177. package/dist/env/ambient.js +35 -0
  178. package/dist/env/ci.d.ts +36 -0
  179. package/dist/env/ci.d.ts.map +1 -0
  180. package/dist/env/ci.js +40 -0
  181. package/dist/env/stem.d.ts +23 -0
  182. package/dist/env/stem.d.ts.map +1 -0
  183. package/dist/env/stem.js +29 -0
  184. package/dist/error/cause.d.ts +143 -0
  185. package/dist/error/cause.d.ts.map +1 -0
  186. package/dist/error/cause.js +192 -0
  187. package/dist/error/client.d.ts +35 -0
  188. package/dist/error/client.d.ts.map +1 -0
  189. package/dist/error/client.js +38 -0
  190. package/dist/error/extend.d.ts +101 -0
  191. package/dist/error/extend.d.ts.map +1 -0
  192. package/dist/error/extend.js +76 -0
  193. package/dist/error/http.d.ts +1516 -0
  194. package/dist/error/http.d.ts.map +1 -0
  195. package/dist/error/http.js +72 -0
  196. package/dist/error/payload.d.ts +3034 -0
  197. package/dist/error/payload.d.ts.map +1 -0
  198. package/dist/error/payload.js +1110 -0
  199. package/dist/error/pithyError.d.ts +154 -0
  200. package/dist/error/pithyError.d.ts.map +1 -0
  201. package/dist/error/pithyError.js +197 -0
  202. package/dist/error/terminal.d.ts +28 -0
  203. package/dist/error/terminal.d.ts.map +1 -0
  204. package/dist/error/terminal.js +33 -0
  205. package/dist/http/authContext.d.ts +21 -0
  206. package/dist/http/authContext.d.ts.map +1 -0
  207. package/dist/http/authContext.js +23 -0
  208. package/dist/http/routeContract.d.ts +39 -0
  209. package/dist/http/routeContract.d.ts.map +1 -0
  210. package/dist/http/routeContract.js +82 -0
  211. package/dist/http/sameOrigin.d.ts +47 -0
  212. package/dist/http/sameOrigin.d.ts.map +1 -0
  213. package/dist/http/sameOrigin.js +24 -0
  214. package/dist/http/signedWebhook.d.ts +225 -0
  215. package/dist/http/signedWebhook.d.ts.map +1 -0
  216. package/dist/http/signedWebhook.js +247 -0
  217. package/dist/http/validation.d.ts +37 -0
  218. package/dist/http/validation.d.ts.map +1 -0
  219. package/dist/http/validation.js +14 -0
  220. package/dist/http/verification.d.ts +10 -0
  221. package/dist/http/verification.d.ts.map +1 -0
  222. package/dist/http/verification.js +17 -0
  223. package/dist/i18n/acceptLanguage.d.ts +22 -0
  224. package/dist/i18n/acceptLanguage.d.ts.map +1 -0
  225. package/dist/i18n/acceptLanguage.js +55 -0
  226. package/dist/i18n/catalog.d.ts +39 -0
  227. package/dist/i18n/catalog.d.ts.map +1 -0
  228. package/dist/i18n/catalog.js +57 -0
  229. package/dist/i18n/locale.d.ts +74 -0
  230. package/dist/i18n/locale.d.ts.map +1 -0
  231. package/dist/i18n/locale.js +109 -0
  232. package/dist/i18n/localeMarker.d.ts +29 -0
  233. package/dist/i18n/localeMarker.d.ts.map +1 -0
  234. package/dist/i18n/localeMarker.js +112 -0
  235. package/dist/i18n/match.d.ts +26 -0
  236. package/dist/i18n/match.d.ts.map +1 -0
  237. package/dist/i18n/match.js +88 -0
  238. package/dist/i18n/registry.d.ts +25 -0
  239. package/dist/i18n/registry.d.ts.map +1 -0
  240. package/dist/i18n/registry.js +51 -0
  241. package/dist/i18n/translator.d.ts +107 -0
  242. package/dist/i18n/translator.d.ts.map +1 -0
  243. package/dist/i18n/translator.js +80 -0
  244. package/dist/index.d.ts +32 -0
  245. package/dist/index.d.ts.map +1 -0
  246. package/dist/index.js +17 -0
  247. package/dist/kv/kv.d.ts +166 -0
  248. package/dist/kv/kv.d.ts.map +1 -0
  249. package/dist/kv/kv.js +261 -0
  250. package/dist/kv/namespaces.d.ts +58 -0
  251. package/dist/kv/namespaces.d.ts.map +1 -0
  252. package/dist/kv/namespaces.js +40 -0
  253. package/dist/logger/local.d.ts +41 -0
  254. package/dist/logger/local.d.ts.map +1 -0
  255. package/dist/logger/local.js +45 -0
  256. package/dist/logger/logger.d.ts +56 -0
  257. package/dist/logger/logger.d.ts.map +1 -0
  258. package/dist/logger/logger.js +83 -0
  259. package/dist/logger/record.d.ts +919 -0
  260. package/dist/logger/record.d.ts.map +1 -0
  261. package/dist/logger/record.js +79 -0
  262. package/dist/logger/worker.d.ts +74 -0
  263. package/dist/logger/worker.d.ts.map +1 -0
  264. package/dist/logger/worker.js +54 -0
  265. package/dist/migrations/batch.d.ts +10 -0
  266. package/dist/migrations/batch.d.ts.map +1 -0
  267. package/dist/migrations/batch.js +193 -0
  268. package/dist/migrations/bookkeeping.d.ts +24 -0
  269. package/dist/migrations/bookkeeping.d.ts.map +1 -0
  270. package/dist/migrations/bookkeeping.js +57 -0
  271. package/dist/migrations/owner.d.ts +41 -0
  272. package/dist/migrations/owner.d.ts.map +1 -0
  273. package/dist/migrations/owner.js +105 -0
  274. package/dist/migrations/registry.d.ts +36 -0
  275. package/dist/migrations/registry.d.ts.map +1 -0
  276. package/dist/migrations/registry.js +70 -0
  277. package/dist/migrations/runner.d.ts +67 -0
  278. package/dist/migrations/runner.d.ts.map +1 -0
  279. package/dist/migrations/runner.js +218 -0
  280. package/dist/naming/domains.d.ts +108 -0
  281. package/dist/naming/domains.d.ts.map +1 -0
  282. package/dist/naming/domains.js +156 -0
  283. package/dist/naming/environment.d.ts +118 -0
  284. package/dist/naming/environment.d.ts.map +1 -0
  285. package/dist/naming/environment.js +190 -0
  286. package/dist/naming/feature.d.ts +68 -0
  287. package/dist/naming/feature.d.ts.map +1 -0
  288. package/dist/naming/feature.js +106 -0
  289. package/dist/naming/limits.d.ts +229 -0
  290. package/dist/naming/limits.d.ts.map +1 -0
  291. package/dist/naming/limits.js +187 -0
  292. package/dist/naming/provisionScope.d.ts +91 -0
  293. package/dist/naming/provisionScope.d.ts.map +1 -0
  294. package/dist/naming/provisionScope.js +65 -0
  295. package/dist/naming/resource.d.ts +169 -0
  296. package/dist/naming/resource.d.ts.map +1 -0
  297. package/dist/naming/resource.js +220 -0
  298. package/dist/naming/resourceNames.d.ts +83 -0
  299. package/dist/naming/resourceNames.d.ts.map +1 -0
  300. package/dist/naming/resourceNames.js +102 -0
  301. package/dist/naming/segment.d.ts +29 -0
  302. package/dist/naming/segment.d.ts.map +1 -0
  303. package/dist/naming/segment.js +31 -0
  304. package/dist/projection/asRead.d.ts +72 -0
  305. package/dist/projection/asRead.d.ts.map +1 -0
  306. package/dist/projection/asRead.js +169 -0
  307. package/dist/projection/published.d.ts +95 -0
  308. package/dist/projection/published.d.ts.map +1 -0
  309. package/dist/projection/published.js +114 -0
  310. package/dist/schema/describedness.d.ts +55 -0
  311. package/dist/schema/describedness.d.ts.map +1 -0
  312. package/dist/schema/describedness.js +180 -0
  313. package/dist/seed/compose.d.ts +41 -0
  314. package/dist/seed/compose.d.ts.map +1 -0
  315. package/dist/seed/compose.js +51 -0
  316. package/dist/seed/devLogin.d.ts +50 -0
  317. package/dist/seed/devLogin.d.ts.map +1 -0
  318. package/dist/seed/devLogin.js +52 -0
  319. package/dist/seed/exampleIdentities.d.ts +58 -0
  320. package/dist/seed/exampleIdentities.d.ts.map +1 -0
  321. package/dist/seed/exampleIdentities.js +26 -0
  322. package/dist/seed/metadata.d.ts +20 -0
  323. package/dist/seed/metadata.d.ts.map +1 -0
  324. package/dist/seed/metadata.js +27 -0
  325. package/dist/seed/seed.d.ts +264 -0
  326. package/dist/seed/seed.d.ts.map +1 -0
  327. package/dist/seed/seed.js +37 -0
  328. package/dist/seed/seededRows.d.ts +26 -0
  329. package/dist/seed/seededRows.d.ts.map +1 -0
  330. package/dist/seed/seededRows.js +20 -0
  331. package/dist/seed/writeD1.d.ts +43 -0
  332. package/dist/seed/writeD1.d.ts.map +1 -0
  333. package/dist/seed/writeD1.js +73 -0
  334. package/dist/seed/writeKv.d.ts +29 -0
  335. package/dist/seed/writeKv.d.ts.map +1 -0
  336. package/dist/seed/writeKv.js +63 -0
  337. package/dist/semver/semver.d.ts +62 -0
  338. package/dist/semver/semver.d.ts.map +1 -0
  339. package/dist/semver/semver.js +137 -0
  340. package/dist/text/comments.d.ts +62 -0
  341. package/dist/text/comments.d.ts.map +1 -0
  342. package/dist/text/comments.js +161 -0
  343. package/dist/version.generated.d.ts +5 -0
  344. package/dist/version.generated.d.ts.map +1 -0
  345. package/dist/version.generated.js +7 -0
  346. package/dist/worker/health.d.ts +39 -0
  347. package/dist/worker/health.d.ts.map +1 -0
  348. package/dist/worker/health.js +41 -0
  349. package/dist/worker/identity.d.ts +191 -0
  350. package/dist/worker/identity.d.ts.map +1 -0
  351. package/dist/worker/identity.js +162 -0
  352. package/dist/workflow/bindings.d.ts +41 -0
  353. package/dist/workflow/bindings.d.ts.map +1 -0
  354. package/dist/workflow/bindings.js +53 -0
  355. package/dist/workflow/dispatch.d.ts +98 -0
  356. package/dist/workflow/dispatch.d.ts.map +1 -0
  357. package/dist/workflow/dispatch.js +148 -0
  358. package/dist/workflow/dispatchRoute.d.ts +80 -0
  359. package/dist/workflow/dispatchRoute.d.ts.map +1 -0
  360. package/dist/workflow/dispatchRoute.js +134 -0
  361. package/dist/workflow/faults.d.ts +97 -0
  362. package/dist/workflow/faults.d.ts.map +1 -0
  363. package/dist/workflow/faults.js +111 -0
  364. package/dist/workflow/host.d.ts +176 -0
  365. package/dist/workflow/host.d.ts.map +1 -0
  366. package/dist/workflow/host.js +116 -0
  367. package/dist/workflow/hostEntry.d.ts +50 -0
  368. package/dist/workflow/hostEntry.d.ts.map +1 -0
  369. package/dist/workflow/hostEntry.js +24 -0
  370. package/dist/workflow/hostEnv.d.ts +143 -0
  371. package/dist/workflow/hostEnv.d.ts.map +1 -0
  372. package/dist/workflow/hostEnv.js +170 -0
  373. package/dist/workflow/loopback.d.ts +52 -0
  374. package/dist/workflow/loopback.d.ts.map +1 -0
  375. package/dist/workflow/loopback.js +76 -0
  376. package/dist/workflow/naming.d.ts +79 -0
  377. package/dist/workflow/naming.d.ts.map +1 -0
  378. package/dist/workflow/naming.js +138 -0
  379. package/dist/workflow/register.d.ts +19 -0
  380. package/dist/workflow/register.d.ts.map +1 -0
  381. package/dist/workflow/register.js +40 -0
  382. package/dist/workflow/schemas.d.ts +44 -0
  383. package/dist/workflow/schemas.d.ts.map +1 -0
  384. package/dist/workflow/schemas.js +43 -0
  385. package/dist/workflow/spec.d.ts +81 -0
  386. package/dist/workflow/spec.d.ts.map +1 -0
  387. package/dist/workflow/spec.js +0 -0
  388. package/dist/workflow/stepMessage.d.ts +122 -0
  389. package/dist/workflow/stepMessage.d.ts.map +1 -0
  390. package/dist/workflow/stepMessage.js +152 -0
  391. package/package.json +20 -9
  392. package/src/capability/manifest.ts +21 -0
  393. package/src/version.generated.ts +1 -1
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Reading a thrown value that no type describes — the one place the kit records **what a runtime does to
3
+ * an error on its way out** (#223), and **the one place that decides whether what it says may be shown**
4
+ * (#228).
5
+ *
6
+ * Nothing here classifies anything. Classification is policy and belongs to the surface that refuses:
7
+ * which causes a loader recognizes, and what each refusal says, differ per surface and are meant to.
8
+ * This module holds only what does not — the facts about the shapes a runtime hands over, and the filter
9
+ * that decides whether one of its strings is safe to put in front of an adopter.
10
+ *
11
+ * **The filter is here for the same reason the facts are, and the argument took two issues to finish.**
12
+ * #223 moved `rootCause`, `prop` and `isBuildFailureWrapper` in and deliberately left `safeReason` beside
13
+ * the three refusals, on the reading that what a surface may say is that surface's business. That is true
14
+ * of the sentences and false of the filter: whether a string carries a path, a stack frame or half a
15
+ * parser's ANSI box is a property of the string, and the answer cannot differ between the CLI, a
16
+ * capability loader and the vite plugin without one of them being wrong. It was three near-verbatim
17
+ * copies, and the hole #223 found in it had to be closed three times (#228).
18
+ *
19
+ * `@pithy-sh/vite` depends on this package and on nothing else in the kit. That constraint is what made
20
+ * core the right home for `rootCause`; it applies to the filter identically.
21
+ */
22
+ /**
23
+ * Read a property off an unknown throwable without widening anything to `any`.
24
+ *
25
+ * Deliberately duck-typed. Bun's `ResolveMessage` and `BuildMessage` — the two shapes the CLI's `bin` and
26
+ * the vite plugin actually catch, since both run on Bun — are their own classes and are **not**
27
+ * `instanceof Error`. An `instanceof` gate here passes a whole suite under vitest, which runs on Node,
28
+ * and silently drops the parser's own sentence on the runtime that ships. That is #207, and it is why
29
+ * every reader of a cause in this kit goes through this function.
30
+ *
31
+ * Non-enumerable properties are read too — `AggregateError.errors` is one, and {@link rootCause}
32
+ * depends on it.
33
+ */
34
+ export declare function prop(cause: unknown, key: string): unknown;
35
+ /**
36
+ * The diagnostic **inside** Bun's `AggregateError` wrapper — the thing a classifier must actually look at.
37
+ *
38
+ * `import()` on Bun hands one build diagnostic over bare and **two or more inside an `AggregateError`**,
39
+ * whose own `message` is `N errors building "<absolute path>"` and whose `Object.keys` is empty. Node
40
+ * throws the diagnostic directly, so no Node-shaped fixture can show this: it is found by running on Bun,
41
+ * and only by running on Bun with a failure of the *realistic* shape.
42
+ *
43
+ * **And the realistic shape is the wrapped one.** A stray brace cascades — one missing `}` in a
44
+ * `pithy.config.ts` produced four diagnostics on Bun 1.3.14 — so a syntax error arrives wrapped far more
45
+ * often than bare. Classified as-is, the wrapper matches nothing: not a resolution failure, not a parse
46
+ * error, just something with a message. The refusal then says *the config threw while loading, run the
47
+ * file directly* while holding the line and column in its hand. #207 fixed the bare case and left this
48
+ * one; #217 hit it in the capability loaders; #223 is it a third time, which is why it lives here.
49
+ *
50
+ * The **first** diagnostic only. The rest are the cascade, not the fault, and naming four positions
51
+ * buries the one that matters.
52
+ *
53
+ * Bounded to four levels: a wrapper holding a wrapper is not a shape any runtime produces today, and an
54
+ * unbounded walk over an adopter's own `errors` field is not something this should be talked into.
55
+ * Anything else — a bare diagnostic, an empty `errors`, a non-array `errors` — is returned untouched, so
56
+ * a runtime that stops wrapping needs no change here.
57
+ */
58
+ export declare function rootCause(cause: unknown): unknown;
59
+ /**
60
+ * The wrapper **after the diagnostics are gone** — a build that failed, and that is all that is left.
61
+ *
62
+ * {@link rootCause} handles the first `import()`. It cannot handle the second: Bun caches a failed module
63
+ * and re-throws an `AggregateError` with **no `errors` at all**, just the count and the path. There is
64
+ * nothing to unwrap, so a classifier that only unwraps reads a syntax error as "it threw" from the second
65
+ * caller onward — which is what `pithy doctor` shows an adopter, because resolving the project's account
66
+ * loads the root config before the report does (#206, #223).
67
+ *
68
+ * Nothing else Bun throws degrades this way: a `ResolveMessage`, a bare `BuildMessage` and a module's own
69
+ * `Error` are byte-identical on every import. Only the wrapper forgets.
70
+ *
71
+ * So the wrapper is recognized by its own message. **What it proves is narrow and worth stating:** the
72
+ * module reached the builder and the builder produced diagnostics. It did not fail to resolve — Bun
73
+ * throws the first `ResolveMessage` bare, wrapping nothing, even for a file with several bad imports —
74
+ * and it did not run, so it cannot have thrown. It failed to parse or to build. A caller may say that
75
+ * much and no more: the message itself carries an absolute path and a count, neither of which is the
76
+ * adopter's business, so it is a *predicate* here rather than a string anyone is tempted to print.
77
+ */
78
+ export declare function isBuildFailureWrapper(cause: unknown): boolean;
79
+ /**
80
+ * The thrown value's message, **de-colored** — `undefined` when it has none.
81
+ *
82
+ * Duck-typed for {@link prop}'s reason. The de-coloring is here rather than at each caller because an
83
+ * escape sequence is formatting the runtime added, not something a surface has an opinion about — and
84
+ * because the three copies of this had already drifted: two stripped with `\u001b`, the third with a
85
+ * literal escape character sitting in its source where no reviewer would see it (#228).
86
+ *
87
+ * This says what the cause *says*. Whether any of it may be shown is {@link safeReason}.
88
+ */
89
+ export declare function causeMessage(cause: unknown): string | undefined;
90
+ /**
91
+ * The cause's own message, but **only when the whole of it is one safe sentence** — the kit's single
92
+ * decision about whether a runtime's string may reach an adopter (#228).
93
+ *
94
+ * A parser's reason (`Expected identifier but found "{"`) is a sentence an adopter acts on. The
95
+ * diagnostic a bundler wraps the same fault in is a multi-line ANSI box quoting an absolute path and the
96
+ * source line, which is throw-site context wearing a message's clothes. What is dropped here still
97
+ * reaches `detail`, which the CLI renderer never prints and the HTTP codec strips — so a refusal costs a
98
+ * developer one frame of digging, and a mistake puts a path, a source line or a stack frame in a field
99
+ * that is rendered.
100
+ *
101
+ * **Provenance first, then content.** Bun's build-failure wrapper is refused outright, before a single
102
+ * content test runs. The content tests exist for a diagnostic that *might* be safe; the wrapper never is,
103
+ * because its whole message is a count nobody asked for and a path that must not travel. Leaving it to
104
+ * the content tests is what leaked: `2 errors building "app/config:12:5.ts"` has no leading slash, sailed
105
+ * through the absolute-path check, and produced *The config does not parse: 2 errors building
106
+ * "app/config:12:5.ts". Line 12, column 5.* — a path the adopter never wrote, and a position fabricated
107
+ * out of a file name (#223). That suppression was written three times because the filter was. It is
108
+ * written once here, and {@link failurePosition} refuses the same shape for the same reason.
109
+ *
110
+ * A trailing period comes off: every caller puts this inside a sentence of its own.
111
+ */
112
+ export declare function safeReason(cause: unknown): string | undefined;
113
+ /** Where a runtime says a failure was. Two numbers, and never the file they were quoted beside. */
114
+ export interface FailurePosition {
115
+ /** 1-based line, as the runtime reported it. */
116
+ line: number;
117
+ /** Column, as the runtime reported it. */
118
+ column: number;
119
+ }
120
+ /**
121
+ * `line`/`column`, from the structured position where a runtime gives one, else from its own `…:LINE:COL`.
122
+ *
123
+ * A recorded fact about two runtimes: Bun's `BuildMessage` carries `position`, and a transform that has no
124
+ * such field states the same thing in its message tail. Only the two numbers are lifted out — never the
125
+ * path they are appended to. Whether a surface prints them is that surface's policy: two of the three
126
+ * classifiers do, and the capability loader deliberately does not.
127
+ *
128
+ * Refuses Bun's build-failure wrapper on provenance, exactly as {@link safeReason} does. That message
129
+ * holds a file name and a count and nothing about where anything failed, so a `:12:5` found in it is a
130
+ * coincidence of the path's own characters — and a fabricated position reads as authoritative.
131
+ */
132
+ export declare function failurePosition(cause: unknown): FailurePosition | undefined;
133
+ /**
134
+ * The specifier that did not resolve.
135
+ *
136
+ * A recorded fact about two runtimes: Bun's `ResolveMessage` carries it as a **field**, and Node states it
137
+ * in prose. The field is preferred wherever there is one, because the prose around it names the referrer's
138
+ * absolute path — the specifier is the adopter's own import, the referrer is our frame.
139
+ *
140
+ * Whether a surface names it, and what it advises when it does, is that surface's policy and stays there.
141
+ */
142
+ export declare function unresolvedSpecifier(cause: unknown): string | undefined;
143
+ //# sourceMappingURL=cause.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cause.d.ts","sourceRoot":"","sources":["../../src/error/cause.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;;;;;;;GAWG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAGzD;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAQjD;AAKD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAG7D;AAeD;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAG/D;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAQ7D;AAED,mGAAmG;AACnG,MAAM,WAAW,eAAe;IAC9B,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,GAAG,SAAS,CAS3E;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAKtE"}
@@ -0,0 +1,192 @@
1
+ //#region src/error/cause.ts
2
+ /**
3
+ * Reading a thrown value that no type describes — the one place the kit records **what a runtime does to
4
+ * an error on its way out** (#223), and **the one place that decides whether what it says may be shown**
5
+ * (#228).
6
+ *
7
+ * Nothing here classifies anything. Classification is policy and belongs to the surface that refuses:
8
+ * which causes a loader recognizes, and what each refusal says, differ per surface and are meant to.
9
+ * This module holds only what does not — the facts about the shapes a runtime hands over, and the filter
10
+ * that decides whether one of its strings is safe to put in front of an adopter.
11
+ *
12
+ * **The filter is here for the same reason the facts are, and the argument took two issues to finish.**
13
+ * #223 moved `rootCause`, `prop` and `isBuildFailureWrapper` in and deliberately left `safeReason` beside
14
+ * the three refusals, on the reading that what a surface may say is that surface's business. That is true
15
+ * of the sentences and false of the filter: whether a string carries a path, a stack frame or half a
16
+ * parser's ANSI box is a property of the string, and the answer cannot differ between the CLI, a
17
+ * capability loader and the vite plugin without one of them being wrong. It was three near-verbatim
18
+ * copies, and the hole #223 found in it had to be closed three times (#228).
19
+ *
20
+ * `@pithy-sh/vite` depends on this package and on nothing else in the kit. That constraint is what made
21
+ * core the right home for `rootCause`; it applies to the filter identically.
22
+ */
23
+ /**
24
+ * Read a property off an unknown throwable without widening anything to `any`.
25
+ *
26
+ * Deliberately duck-typed. Bun's `ResolveMessage` and `BuildMessage` — the two shapes the CLI's `bin` and
27
+ * the vite plugin actually catch, since both run on Bun — are their own classes and are **not**
28
+ * `instanceof Error`. An `instanceof` gate here passes a whole suite under vitest, which runs on Node,
29
+ * and silently drops the parser's own sentence on the runtime that ships. That is #207, and it is why
30
+ * every reader of a cause in this kit goes through this function.
31
+ *
32
+ * Non-enumerable properties are read too — `AggregateError.errors` is one, and {@link rootCause}
33
+ * depends on it.
34
+ */
35
+ function prop(cause, key) {
36
+ if (typeof cause !== "object" || cause === null) return void 0;
37
+ return cause[key];
38
+ }
39
+ /**
40
+ * The diagnostic **inside** Bun's `AggregateError` wrapper — the thing a classifier must actually look at.
41
+ *
42
+ * `import()` on Bun hands one build diagnostic over bare and **two or more inside an `AggregateError`**,
43
+ * whose own `message` is `N errors building "<absolute path>"` and whose `Object.keys` is empty. Node
44
+ * throws the diagnostic directly, so no Node-shaped fixture can show this: it is found by running on Bun,
45
+ * and only by running on Bun with a failure of the *realistic* shape.
46
+ *
47
+ * **And the realistic shape is the wrapped one.** A stray brace cascades — one missing `}` in a
48
+ * `pithy.config.ts` produced four diagnostics on Bun 1.3.14 — so a syntax error arrives wrapped far more
49
+ * often than bare. Classified as-is, the wrapper matches nothing: not a resolution failure, not a parse
50
+ * error, just something with a message. The refusal then says *the config threw while loading, run the
51
+ * file directly* while holding the line and column in its hand. #207 fixed the bare case and left this
52
+ * one; #217 hit it in the capability loaders; #223 is it a third time, which is why it lives here.
53
+ *
54
+ * The **first** diagnostic only. The rest are the cascade, not the fault, and naming four positions
55
+ * buries the one that matters.
56
+ *
57
+ * Bounded to four levels: a wrapper holding a wrapper is not a shape any runtime produces today, and an
58
+ * unbounded walk over an adopter's own `errors` field is not something this should be talked into.
59
+ * Anything else — a bare diagnostic, an empty `errors`, a non-array `errors` — is returned untouched, so
60
+ * a runtime that stops wrapping needs no change here.
61
+ */
62
+ function rootCause(cause) {
63
+ let current = cause;
64
+ for (let depth = 0; depth < 4; depth += 1) {
65
+ const errors = prop(current, "errors");
66
+ if (!Array.isArray(errors) || errors.length === 0 || errors[0] === void 0) return current;
67
+ current = errors[0];
68
+ }
69
+ return current;
70
+ }
71
+ /** Bun's wrapper announces itself: `4 errors building "<absolute path>"`, and nothing else says that. */
72
+ const BUILD_FAILURE = /^\d+ errors? building "/;
73
+ /**
74
+ * The wrapper **after the diagnostics are gone** — a build that failed, and that is all that is left.
75
+ *
76
+ * {@link rootCause} handles the first `import()`. It cannot handle the second: Bun caches a failed module
77
+ * and re-throws an `AggregateError` with **no `errors` at all**, just the count and the path. There is
78
+ * nothing to unwrap, so a classifier that only unwraps reads a syntax error as "it threw" from the second
79
+ * caller onward — which is what `pithy doctor` shows an adopter, because resolving the project's account
80
+ * loads the root config before the report does (#206, #223).
81
+ *
82
+ * Nothing else Bun throws degrades this way: a `ResolveMessage`, a bare `BuildMessage` and a module's own
83
+ * `Error` are byte-identical on every import. Only the wrapper forgets.
84
+ *
85
+ * So the wrapper is recognized by its own message. **What it proves is narrow and worth stating:** the
86
+ * module reached the builder and the builder produced diagnostics. It did not fail to resolve — Bun
87
+ * throws the first `ResolveMessage` bare, wrapping nothing, even for a file with several bad imports —
88
+ * and it did not run, so it cannot have thrown. It failed to parse or to build. A caller may say that
89
+ * much and no more: the message itself carries an absolute path and a count, neither of which is the
90
+ * adopter's business, so it is a *predicate* here rather than a string anyone is tempted to print.
91
+ */
92
+ function isBuildFailureWrapper(cause) {
93
+ const message = prop(cause, "message");
94
+ return typeof message === "string" && BUILD_FAILURE.test(message);
95
+ }
96
+ /** Escape sequences a runtime colors its diagnostics with. They are formatting, and they never travel. */
97
+ const ANSI = /\u001b\[[0-9;]*m/g;
98
+ /** Anything that looks like the start of an absolute path — POSIX, `~`, or a Windows drive. */
99
+ const ABSOLUTE_PATH = /(^|[\s'"(])(\/|~\/|[A-Za-z]:[\\/])/;
100
+ /** A stack frame, in the one spelling every runtime here agrees on. */
101
+ const STACK_FRAME = /\bat \S+:\d+:\d+/;
102
+ /** The longest a reason may be before it has stopped being a sentence and started being a diagnostic. */
103
+ const REASON_LIMIT = 160;
104
+ /**
105
+ * The thrown value's message, **de-colored** — `undefined` when it has none.
106
+ *
107
+ * Duck-typed for {@link prop}'s reason. The de-coloring is here rather than at each caller because an
108
+ * escape sequence is formatting the runtime added, not something a surface has an opinion about — and
109
+ * because the three copies of this had already drifted: two stripped with `\u001b`, the third with a
110
+ * literal escape character sitting in its source where no reviewer would see it (#228).
111
+ *
112
+ * This says what the cause *says*. Whether any of it may be shown is {@link safeReason}.
113
+ */
114
+ function causeMessage(cause) {
115
+ const message = prop(cause, "message");
116
+ return typeof message === "string" ? message.replace(ANSI, "") : void 0;
117
+ }
118
+ /**
119
+ * The cause's own message, but **only when the whole of it is one safe sentence** — the kit's single
120
+ * decision about whether a runtime's string may reach an adopter (#228).
121
+ *
122
+ * A parser's reason (`Expected identifier but found "{"`) is a sentence an adopter acts on. The
123
+ * diagnostic a bundler wraps the same fault in is a multi-line ANSI box quoting an absolute path and the
124
+ * source line, which is throw-site context wearing a message's clothes. What is dropped here still
125
+ * reaches `detail`, which the CLI renderer never prints and the HTTP codec strips — so a refusal costs a
126
+ * developer one frame of digging, and a mistake puts a path, a source line or a stack frame in a field
127
+ * that is rendered.
128
+ *
129
+ * **Provenance first, then content.** Bun's build-failure wrapper is refused outright, before a single
130
+ * content test runs. The content tests exist for a diagnostic that *might* be safe; the wrapper never is,
131
+ * because its whole message is a count nobody asked for and a path that must not travel. Leaving it to
132
+ * the content tests is what leaked: `2 errors building "app/config:12:5.ts"` has no leading slash, sailed
133
+ * through the absolute-path check, and produced *The config does not parse: 2 errors building
134
+ * "app/config:12:5.ts". Line 12, column 5.* — a path the adopter never wrote, and a position fabricated
135
+ * out of a file name (#223). That suppression was written three times because the filter was. It is
136
+ * written once here, and {@link failurePosition} refuses the same shape for the same reason.
137
+ *
138
+ * A trailing period comes off: every caller puts this inside a sentence of its own.
139
+ */
140
+ function safeReason(cause) {
141
+ if (isBuildFailureWrapper(cause)) return void 0;
142
+ const text = (causeMessage(cause) ?? "").trim();
143
+ if (text.length === 0 || text.length > REASON_LIMIT) return void 0;
144
+ if (text.includes("\n")) return void 0;
145
+ if (ABSOLUTE_PATH.test(text)) return void 0;
146
+ if (STACK_FRAME.test(text)) return void 0;
147
+ return text.replace(/\.$/, "");
148
+ }
149
+ /**
150
+ * `line`/`column`, from the structured position where a runtime gives one, else from its own `…:LINE:COL`.
151
+ *
152
+ * A recorded fact about two runtimes: Bun's `BuildMessage` carries `position`, and a transform that has no
153
+ * such field states the same thing in its message tail. Only the two numbers are lifted out — never the
154
+ * path they are appended to. Whether a surface prints them is that surface's policy: two of the three
155
+ * classifiers do, and the capability loader deliberately does not.
156
+ *
157
+ * Refuses Bun's build-failure wrapper on provenance, exactly as {@link safeReason} does. That message
158
+ * holds a file name and a count and nothing about where anything failed, so a `:12:5` found in it is a
159
+ * coincidence of the path's own characters — and a fabricated position reads as authoritative.
160
+ */
161
+ function failurePosition(cause) {
162
+ if (isBuildFailureWrapper(cause)) return void 0;
163
+ const position = prop(cause, "position");
164
+ const line = prop(position, "line");
165
+ const column = prop(position, "column");
166
+ if (typeof line === "number" && line > 0 && typeof column === "number") return {
167
+ line,
168
+ column
169
+ };
170
+ const match = /:(\d+):(\d+)/.exec(causeMessage(cause) ?? "");
171
+ if (!match?.[1] || !match[2]) return void 0;
172
+ return {
173
+ line: Number(match[1]),
174
+ column: Number(match[2])
175
+ };
176
+ }
177
+ /**
178
+ * The specifier that did not resolve.
179
+ *
180
+ * A recorded fact about two runtimes: Bun's `ResolveMessage` carries it as a **field**, and Node states it
181
+ * in prose. The field is preferred wherever there is one, because the prose around it names the referrer's
182
+ * absolute path — the specifier is the adopter's own import, the referrer is our frame.
183
+ *
184
+ * Whether a surface names it, and what it advises when it does, is that surface's policy and stays there.
185
+ */
186
+ function unresolvedSpecifier(cause) {
187
+ const field = prop(cause, "specifier");
188
+ if (typeof field === "string" && field.length > 0) return field;
189
+ return /Cannot find (?:package|module) ['"]([^'"]+)['"]/.exec(causeMessage(cause) ?? "")?.[1];
190
+ }
191
+ //#endregion
192
+ export { causeMessage, failurePosition, isBuildFailureWrapper, prop, rootCause, safeReason, unresolvedSpecifier };
@@ -0,0 +1,35 @@
1
+ import type { z } from "zod";
2
+ import type { ErrorPayload } from "./payload";
3
+ import { PublicErrorPayload } from "./payload";
4
+ /**
5
+ * **The one place an error becomes bytes for a client.** Whatever the transport.
6
+ *
7
+ * An error leaves this process by more than one road. A JSON response is the busiest, and it had the
8
+ * boundary written into it — but a Durable Object also pushes error frames down a WebSocket, and a
9
+ * transport that grew its own projection grew its own idea of what a client may read. That is how
10
+ * `action` reached a browser after the schema had already classified it: not because anyone disagreed
11
+ * with the rule, but because the rule lived inside the HTTP codec, and a socket is not HTTP.
12
+ *
13
+ * So the rule sits here, above every transport, and each transport calls it:
14
+ *
15
+ * - `HttpError.encode` (./http) — the JSON body of a response.
16
+ * - The multiplayer session Durable Object — the `error` frame on a player's socket.
17
+ * - Anything added next. An SSE `event:`, a queue consumer echoing a failure, a Workflow surfacing one.
18
+ * None of them needs to know *what* is stripped; they need to know they must come through here.
19
+ *
20
+ * What it strips, and why that is not a list to maintain: `action` and `detail` are removed by name,
21
+ * and the result is then parsed by `PublicErrorPayload`, which has neither key. The parse is what makes
22
+ * the boundary hold for an **adopter's** code as well as the kit's — it is a property of the schema, so
23
+ * a field classified as operator-facing tomorrow is stripped here without this function changing.
24
+ *
25
+ * The mirror is {@link operatorError} in ./terminal, which keeps `action` because whoever ran the
26
+ * command is the person who can act on "Bind a D1 database named DB in wrangler.jsonc". Two audiences,
27
+ * two functions, and neither one is a transport.
28
+ *
29
+ * It takes the **input** side of `ErrorPayload` rather than the output side, which is the wider of the
30
+ * two: an adopter's code carries a brand once parsed, and a codec's encode side is handed the shape
31
+ * before that brand exists. A `PithyError`'s own payload satisfies it either way, and the brand is not
32
+ * something this function needs — it parses what it is given.
33
+ */
34
+ export declare function clientError(payload: z.input<typeof ErrorPayload>): PublicErrorPayload;
35
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/error/client.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,GAAG,kBAAkB,CAKrF"}
@@ -0,0 +1,38 @@
1
+ import { PublicErrorPayload } from "./payload.js";
2
+ //#region src/error/client.ts
3
+ /**
4
+ * **The one place an error becomes bytes for a client.** Whatever the transport.
5
+ *
6
+ * An error leaves this process by more than one road. A JSON response is the busiest, and it had the
7
+ * boundary written into it — but a Durable Object also pushes error frames down a WebSocket, and a
8
+ * transport that grew its own projection grew its own idea of what a client may read. That is how
9
+ * `action` reached a browser after the schema had already classified it: not because anyone disagreed
10
+ * with the rule, but because the rule lived inside the HTTP codec, and a socket is not HTTP.
11
+ *
12
+ * So the rule sits here, above every transport, and each transport calls it:
13
+ *
14
+ * - `HttpError.encode` (./http) — the JSON body of a response.
15
+ * - The multiplayer session Durable Object — the `error` frame on a player's socket.
16
+ * - Anything added next. An SSE `event:`, a queue consumer echoing a failure, a Workflow surfacing one.
17
+ * None of them needs to know *what* is stripped; they need to know they must come through here.
18
+ *
19
+ * What it strips, and why that is not a list to maintain: `action` and `detail` are removed by name,
20
+ * and the result is then parsed by `PublicErrorPayload`, which has neither key. The parse is what makes
21
+ * the boundary hold for an **adopter's** code as well as the kit's — it is a property of the schema, so
22
+ * a field classified as operator-facing tomorrow is stripped here without this function changing.
23
+ *
24
+ * The mirror is {@link operatorError} in ./terminal, which keeps `action` because whoever ran the
25
+ * command is the person who can act on "Bind a D1 database named DB in wrangler.jsonc". Two audiences,
26
+ * two functions, and neither one is a transport.
27
+ *
28
+ * It takes the **input** side of `ErrorPayload` rather than the output side, which is the wider of the
29
+ * two: an adopter's code carries a brand once parsed, and a codec's encode side is handed the shape
30
+ * before that brand exists. A `PithyError`'s own payload satisfies it either way, and the brand is not
31
+ * something this function needs — it parses what it is given.
32
+ */
33
+ function clientError(payload) {
34
+ const { action: _action, detail: _detail, ...wire } = payload;
35
+ return PublicErrorPayload.parse(wire);
36
+ }
37
+ //#endregion
38
+ export { clientError };
@@ -0,0 +1,101 @@
1
+ import type { MessageParams } from "../i18n/catalog";
2
+ import type { ErrorPayload, KitErrorDomain } from "./payload";
3
+ import { ExtendedErrorPayload } from "./payload";
4
+ /**
5
+ * A kit domain used in an adopter's code. The false branch is `unknown`, which intersects away; the
6
+ * true branch is a string the caller's own `code` cannot possibly be, so the mistake surfaces at the
7
+ * declaration with its reason spelled out in the type error rather than as `never`.
8
+ */
9
+ type ReservedDomain<Code extends string> = Code extends `${KitErrorDomain}/${string}` ? {
10
+ code: "That domain is the kit's. Namespace your code under a domain of your own.";
11
+ } : unknown;
12
+ /**
13
+ * The payload behind one code, kit or adopter. `Extract` finds a kit member by its literal `code`;
14
+ * an adopter's code is branded and so extracts to nothing, and the open member stands in with the
15
+ * literal intersected back on. Type a vehicle class with it exactly as the kit's own subclasses are:
16
+ * `declare readonly payload: ErrorPayloadOf<"connect/device_code_expired">`.
17
+ */
18
+ export type ErrorPayloadOf<Code extends string> = [Extract<ErrorPayload, {
19
+ code: Code;
20
+ }>] extends [never] ? ExtendedErrorPayload & {
21
+ code: Code;
22
+ } : Extract<ErrorPayload, {
23
+ code: Code;
24
+ }>;
25
+ /**
26
+ * Narrow a caught payload to one code. `payload.code === "core/not_found"` narrows a kit member on
27
+ * its own, but an adopter's code is branded — the brand is what keeps a kit narrow honest — so the
28
+ * same comparison against a bare literal is a type error, and `Extract` on it is silently `never`.
29
+ * This is the way in for both: one guard, kit codes and adopter codes alike.
30
+ *
31
+ * ```ts
32
+ * catch (error) {
33
+ * if (error instanceof PithyError && isErrorCode(error.payload, "connect/device_code_expired")) {
34
+ * return restartDeviceFlow();
35
+ * }
36
+ * }
37
+ * ```
38
+ */
39
+ export declare function isErrorCode<const Code extends `${string}/${string}`>(payload: ErrorPayload, code: Code): payload is ErrorPayloadOf<Code>;
40
+ /**
41
+ * The one door into `ErrorPayload` for a code the kit does not define. An adopter writing a control
42
+ * plane, a device-code flow, or a key-rotation lock has failures the kit has no word for; without
43
+ * this they reuse a kit code that means something else, or stop throwing `PithyError` at all.
44
+ *
45
+ * It is a function rather than a plain object literal for the same reason `defineSecretRegistry` is:
46
+ * the declaration is where the mistake is, so the declaration is where it should fail. A code under
47
+ * one of the kit's domains does not compile — the kit's domains are reserved the way `pithy_` table
48
+ * names are, so nobody redefines `auth/forbidden` with a status of their choosing, and a
49
+ * capability's own typo stays a hard failure instead of becoming somebody's custom error. The parse
50
+ * below is the second gate, for the grammar, the 4xx/5xx bound, and any caller who cast their way
51
+ * past the first.
52
+ *
53
+ * What it does **not** do is pin a status to a code. A kit member fixes one status per code, and
54
+ * that cannot survive a set the kit does not hold: this seam bounds the range and nothing more, so
55
+ * throwing `connect/device_code_expired` as a 410 from one site and a 500 from another passes every
56
+ * layer. Declare each of your codes in one vehicle class, once, and that stays true by construction.
57
+ *
58
+ * It does not move the security boundary either. The payload it returns carries `action` and
59
+ * `detail` exactly like a kit member, and the HTTP codec strips both from every member alike. An
60
+ * adopter cannot opt into leaking, because there is nothing to opt into — the wire shape has no such
61
+ * key to fill, whoever defined the code.
62
+ *
63
+ * ```ts
64
+ * export class DeviceCodeExpiredError extends PithyError {
65
+ * declare readonly payload: ErrorPayloadOf<"connect/device_code_expired">;
66
+ *
67
+ * constructor(detail?: string) {
68
+ * super(defineErrorPayload({
69
+ * code: "connect/device_code_expired",
70
+ * status: 410,
71
+ * message: "That device code has expired.",
72
+ * action: "Run pithy dashboard connect again.",
73
+ * detail,
74
+ * }));
75
+ * }
76
+ * }
77
+ * ```
78
+ */
79
+ export declare function defineErrorPayload<const Code extends `${string}/${string}`>(payload: {
80
+ /** `domain/reason`, lower snake_case, under a domain of the adopter's own — never one the kit uses. */
81
+ code: Code;
82
+ /** The HTTP status this code maps to. A 4xx or a 5xx — an error is not a success. */
83
+ status: number;
84
+ /** Public, safe-to-expose summary. Sent to clients and shown in the terminal. */
85
+ message: string;
86
+ /** Operator remediation hint. Becomes the CLI action line. Never sent to a client. */
87
+ action?: string;
88
+ /** Internal context for logs + audit. NEVER serialized to clients — the HTTP codec strips it. */
89
+ detail?: string;
90
+ /**
91
+ * Values a translating client interpolates into its own wording for this code. Client-facing:
92
+ * these cross the boundary with `message`, unlike `action` and `detail`.
93
+ *
94
+ * Stated here because this parameter type is **hand-written**, not derived from the schema, and
95
+ * the `as ErrorPayloadOf<Code>` below hides the gap from the compiler. A field left off this
96
+ * literal is not a type error anywhere — it is simply a field an adopter cannot pass.
97
+ */
98
+ params?: MessageParams;
99
+ } & ReservedDomain<Code>): ErrorPayloadOf<Code>;
100
+ export {};
101
+ //# sourceMappingURL=extend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extend.d.ts","sourceRoot":"","sources":["../../src/error/extend.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAMjD;;;;GAIG;AACH,KAAK,cAAc,CAAC,IAAI,SAAS,MAAM,IAAI,IAAI,SAAS,GAAG,cAAc,IAAI,MAAM,EAAE,GACjF;IAAE,IAAI,EAAE,2EAA2E,CAAA;CAAE,GACrF,OAAO,CAAC;AAEZ;;;;;GAKG;AACH,MAAM,MAAM,cAAc,CAAC,IAAI,SAAS,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GACrG,oBAAoB,GAAG;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,GACrC,OAAO,CAAC,YAAY,EAAE;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC,CAAC;AAE1C;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,KAAK,CAAC,IAAI,SAAS,GAAG,MAAM,IAAI,MAAM,EAAE,EAClE,OAAO,EAAE,YAAY,EACrB,IAAI,EAAE,IAAI,GACT,OAAO,IAAI,cAAc,CAAC,IAAI,CAAC,CAEjC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,IAAI,SAAS,GAAG,MAAM,IAAI,MAAM,EAAE,EACzE,OAAO,EAAE;IACP,uGAAuG;IACvG,IAAI,EAAE,IAAI,CAAC;IACX,qFAAqF;IACrF,MAAM,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC;IAChB,sFAAsF;IACtF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iGAAiG;IACjG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB,GAAG,cAAc,CAAC,IAAI,CAAC,GACvB,cAAc,CAAC,IAAI,CAAC,CAiBtB"}
@@ -0,0 +1,76 @@
1
+ import { ExtendedErrorPayload } from "./payload.js";
2
+ import { InternalError } from "./pithyError.js";
3
+ //#region src/error/extend.ts
4
+ /** How much of a rejected code the public message will quote. Enough to debug, not enough to abuse. */
5
+ const QUOTED_CODE_LIMIT = 72;
6
+ /**
7
+ * Narrow a caught payload to one code. `payload.code === "core/not_found"` narrows a kit member on
8
+ * its own, but an adopter's code is branded — the brand is what keeps a kit narrow honest — so the
9
+ * same comparison against a bare literal is a type error, and `Extract` on it is silently `never`.
10
+ * This is the way in for both: one guard, kit codes and adopter codes alike.
11
+ *
12
+ * ```ts
13
+ * catch (error) {
14
+ * if (error instanceof PithyError && isErrorCode(error.payload, "connect/device_code_expired")) {
15
+ * return restartDeviceFlow();
16
+ * }
17
+ * }
18
+ * ```
19
+ */
20
+ function isErrorCode(payload, code) {
21
+ return payload.code === code;
22
+ }
23
+ /**
24
+ * The one door into `ErrorPayload` for a code the kit does not define. An adopter writing a control
25
+ * plane, a device-code flow, or a key-rotation lock has failures the kit has no word for; without
26
+ * this they reuse a kit code that means something else, or stop throwing `PithyError` at all.
27
+ *
28
+ * It is a function rather than a plain object literal for the same reason `defineSecretRegistry` is:
29
+ * the declaration is where the mistake is, so the declaration is where it should fail. A code under
30
+ * one of the kit's domains does not compile — the kit's domains are reserved the way `pithy_` table
31
+ * names are, so nobody redefines `auth/forbidden` with a status of their choosing, and a
32
+ * capability's own typo stays a hard failure instead of becoming somebody's custom error. The parse
33
+ * below is the second gate, for the grammar, the 4xx/5xx bound, and any caller who cast their way
34
+ * past the first.
35
+ *
36
+ * What it does **not** do is pin a status to a code. A kit member fixes one status per code, and
37
+ * that cannot survive a set the kit does not hold: this seam bounds the range and nothing more, so
38
+ * throwing `connect/device_code_expired` as a 410 from one site and a 500 from another passes every
39
+ * layer. Declare each of your codes in one vehicle class, once, and that stays true by construction.
40
+ *
41
+ * It does not move the security boundary either. The payload it returns carries `action` and
42
+ * `detail` exactly like a kit member, and the HTTP codec strips both from every member alike. An
43
+ * adopter cannot opt into leaking, because there is nothing to opt into — the wire shape has no such
44
+ * key to fill, whoever defined the code.
45
+ *
46
+ * ```ts
47
+ * export class DeviceCodeExpiredError extends PithyError {
48
+ * declare readonly payload: ErrorPayloadOf<"connect/device_code_expired">;
49
+ *
50
+ * constructor(detail?: string) {
51
+ * super(defineErrorPayload({
52
+ * code: "connect/device_code_expired",
53
+ * status: 410,
54
+ * message: "That device code has expired.",
55
+ * action: "Run pithy dashboard connect again.",
56
+ * detail,
57
+ * }));
58
+ * }
59
+ * }
60
+ * ```
61
+ */
62
+ function defineErrorPayload(payload) {
63
+ const parsed = ExtendedErrorPayload.safeParse(payload);
64
+ if (!parsed.success) throw new InternalError({
65
+ message: `error payload: "${quoteCode(payload.code)}" (${payload.status}) is not a usable adopter error code.`,
66
+ action: "Use `<your_domain>/<reason>` in lower snake_case, a 4xx or 5xx status, and a domain the kit does not own.",
67
+ detail: parsed.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ")
68
+ });
69
+ return parsed.data;
70
+ }
71
+ /** The offending code, bounded, for an author-error message that reaches a client. */
72
+ function quoteCode(code) {
73
+ return code.length <= QUOTED_CODE_LIMIT ? code : `${code.slice(0, QUOTED_CODE_LIMIT)}…`;
74
+ }
75
+ //#endregion
76
+ export { defineErrorPayload, isErrorCode };