@pithy-sh/core 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,170 @@
1
+ import { InternalError } from "../error/pithyError.js";
2
+ import { createWorkerLogger } from "../logger/worker.js";
3
+ import { z } from "zod";
4
+ //#region src/workflow/hostEnv.ts
5
+ /**
6
+ * What a capability host worker reads out of its env, and what fills each of it.
7
+ *
8
+ * A host is a Worker nobody authored: `pithy <capability> provision` resolves a committed template
9
+ * (see {@link ./host.ts}) and deploys it. Everything it needs therefore arrives as a binding, a var,
10
+ * a Secrets Store entry or a serialized config blob — and until this module, **none of it was
11
+ * validated anywhere.** `@pithy-sh/email`'s host read fourteen fields raw: a missing `BASE_URL`
12
+ * became a magic link to `undefined/…`, an unparseable `EMAIL_THEME` threw inside a render step
13
+ * three retries deep, and a `SCHEDULER_BATCH_SIZE` somebody typed as `"fifty"` became `NaN`, so the
14
+ * scheduler claimed nothing, quietly, forever. Every one of those is discovered as a mail that did
15
+ * not arrive.
16
+ *
17
+ * So a host declares its env once, as a Zod object with a `.describe()` per field, and pairs each
18
+ * field with the thing that provides it. Two consumers read that one declaration:
19
+ *
20
+ * - the host itself, at boot, through {@link requireHostEnv} — one legible block naming every
21
+ * unusable value and what fills it, then a refusal. A host that cannot work does not wait to be
22
+ * asked.
23
+ * - `pithy doctor`, statically, through {@link hostEnvFields} and {@link checkHostEnv} — the same
24
+ * schema, so the check an operator runs and the check the host runs cannot disagree.
25
+ *
26
+ * ## Kept importable from the CLI
27
+ *
28
+ * No `cloudflare:` import, no Node builtin, no filesystem — the same constraint {@link ./host.ts}
29
+ * carries, and for the same reason: `pithy doctor` runs under node and imports this to read a
30
+ * capability's declaration without executing its Worker.
31
+ */
32
+ /** The kinds of thing that can fill a host env field. One of these names is what an operator acts on. */
33
+ const HostEnvProviderKind = z.enum([
34
+ "binding",
35
+ "var",
36
+ "secret",
37
+ "config"
38
+ ]).describe("Where a host env field comes from: a Worker `binding`, a wrangler `var`, a `secret` read through @pithy-sh/secrets, or a `config` key in the adopter's pithy.config.ts.");
39
+ /**
40
+ * What provides one field. The whole point of the declaration: a report that says `BASE_URL is
41
+ * missing` sends a developer looking, and a report that says `Var BASE_URL in the host's
42
+ * wrangler.jsonc. Run pithy email provision --env dev.` ends the search.
43
+ */
44
+ const HostEnvProvider = z.object({
45
+ kind: HostEnvProviderKind.describe("Which kind of thing fills this field."),
46
+ name: z.string().min(1).describe("The binding name, var name, secret name, or config key — spelled exactly as it is authored."),
47
+ command: z.string().min(1).optional().describe("The `pithy` command that fills it, where one does. Rendered as the report's action line.")
48
+ }).describe("What fills one field of a host worker's env, so a failure names the thing an operator changes.");
49
+ /**
50
+ * Declare a host's env. The mapped `provided` type makes an unaccounted field a compile error; the
51
+ * runtime check below makes it an error for a declaration the CLI reads back off a package it never
52
+ * compiled, which is the case `pithy doctor` is entirely made of.
53
+ */
54
+ function defineHostEnv(declaration) {
55
+ const unaccounted = Object.keys(declaration.env.shape).filter((field) => !(field in declaration.provided));
56
+ if (unaccounted.length > 0) throw new InternalError({
57
+ message: `The ${declaration.capability} host env declares fields nothing provides.`,
58
+ action: "Add a provider for each field: the binding, var, secret, or config key that fills it.",
59
+ detail: `Unaccounted fields: ${unaccounted.join(", ")}.`
60
+ });
61
+ return declaration;
62
+ }
63
+ /** The provider reported for a field the declaration never accounted for. Should be unreachable. */
64
+ function undeclaredProvider(field) {
65
+ return {
66
+ kind: "var",
67
+ name: field
68
+ };
69
+ }
70
+ /**
71
+ * Check an env against a declaration. Pure: it parses, it reports, and it neither logs nor throws —
72
+ * which is what lets `pithy doctor` run the host's own check without a Worker.
73
+ *
74
+ * One problem per field, even where Zod raises several issues for it: an operator fixes a field, not
75
+ * an issue, and three lines about `EMAIL_THEME` push the field they have not read yet off the block.
76
+ */
77
+ function checkHostEnv(declaration, env) {
78
+ const subject = typeof env === "object" && env !== null ? env : {};
79
+ const parsed = declaration.env.safeParse(subject);
80
+ if (parsed.success) return {
81
+ ok: true,
82
+ value: parsed.data,
83
+ problems: []
84
+ };
85
+ const reasons = /* @__PURE__ */ new Map();
86
+ for (const issue of parsed.error.issues) {
87
+ const field = issue.path[0];
88
+ if (typeof field !== "string" || reasons.has(field)) continue;
89
+ reasons.set(field, issue.message);
90
+ }
91
+ const problems = [];
92
+ for (const field of Object.keys(declaration.env.shape)) {
93
+ const reason = reasons.get(field);
94
+ if (reason === void 0) continue;
95
+ problems.push({
96
+ field,
97
+ reason,
98
+ provider: declaration.provided[field] ?? undeclaredProvider(field)
99
+ });
100
+ }
101
+ return {
102
+ ok: false,
103
+ value: void 0,
104
+ problems
105
+ };
106
+ }
107
+ /** One sentence naming the thing an operator changes, plus the command that writes it where there is one. */
108
+ function hostEnvProviderSentence(provider) {
109
+ const where = provider.kind === "binding" ? `Binding ${provider.name} in the host's wrangler.jsonc.` : provider.kind === "var" ? `Var ${provider.name} in the host's wrangler.jsonc.` : provider.kind === "secret" ? `Secret ${provider.name}, read through @pithy-sh/secrets.` : `Config key ${provider.name}.`;
110
+ return provider.command ? `${where} Run ${provider.command}.` : where;
111
+ }
112
+ /**
113
+ * The block a host logs before it refuses. One headline, then one line per field: the field, why it
114
+ * is unusable, and what fills it. Brand voice — short sentences, deliberate periods, no decoration
115
+ * that a log aggregator would have to strip.
116
+ */
117
+ function renderHostEnvProblems(capability, problems) {
118
+ const lines = problems.map((problem) => ` ${problem.field} — ${problem.reason} ${hostEnvProviderSentence(problem.provider)}`);
119
+ return [`The ${capability} host cannot start. ${problems.length === 1 ? "1 setting is" : `${problems.length} settings are`} missing or unusable.`, ...lines].join("\n");
120
+ }
121
+ /**
122
+ * Every env object this process has already reported on, so a boot path that asks twice logs once.
123
+ *
124
+ * A module-scope call in a Worker happens once per isolate and needs no help; a host that validates
125
+ * inside `fetch` — or a `scheduled` handler firing every minute — would otherwise write the same
126
+ * block into Workers Logs forever, which is how a legible block becomes noise nobody reads.
127
+ */
128
+ const reported = /* @__PURE__ */ new WeakSet();
129
+ /**
130
+ * Validate a host's env, or say exactly what is wrong and refuse.
131
+ *
132
+ * Called at boot, before the host serves anything. The block goes to the log (the operator's
133
+ * audience, so it carries the provider lines) and the refusal is `core/internal`: a host that cannot
134
+ * parse config *we* generated is our failure, and our logs are where the answer is (CLAUDE.md
135
+ * §Errors). Nothing about the values themselves is logged — a provider name is a location, never a
136
+ * secret.
137
+ */
138
+ function requireHostEnv(declaration, env, log = createWorkerLogger()) {
139
+ const report = checkHostEnv(declaration, env);
140
+ if (report.ok && report.value !== void 0) return report.value;
141
+ const block = renderHostEnvProblems(declaration.capability, report.problems);
142
+ if (typeof env !== "object" || env === null || !reported.has(env)) {
143
+ if (typeof env === "object" && env !== null) reported.add(env);
144
+ log.error(block, {
145
+ capability: declaration.capability,
146
+ fields: report.problems.map((problem) => problem.field)
147
+ });
148
+ }
149
+ throw new InternalError({
150
+ message: `The ${declaration.capability} host is not configured.`,
151
+ action: "Read the startup log: it names every unusable setting and what fills it.",
152
+ detail: block
153
+ });
154
+ }
155
+ /**
156
+ * Read a declaration statically: what the host needs, what documents each field, and what fills it.
157
+ *
158
+ * The static half of this module, and the one `pithy doctor` builds its report from (#411). Field
159
+ * order is the schema's, so a report reads in the order the capability chose to explain itself.
160
+ */
161
+ function hostEnvFields(declaration) {
162
+ return Object.entries(declaration.env.shape).map(([field, schema]) => ({
163
+ field,
164
+ description: schema.description,
165
+ provider: declaration.provided[field] ?? undeclaredProvider(field),
166
+ optional: schema.safeParse(void 0).success
167
+ }));
168
+ }
169
+ //#endregion
170
+ export { HostEnvProvider, HostEnvProviderKind, checkHostEnv, defineHostEnv, hostEnvFields, hostEnvProviderSentence, renderHostEnvProblems, requireHostEnv };
@@ -0,0 +1,52 @@
1
+ import type { WorkflowBinding } from "./spec";
2
+ /**
3
+ * The loopback dispatcher: the one-method dispatch seam, carried over a sibling's origin instead of
4
+ * a cross-script binding.
5
+ *
6
+ * `pithy dev` composes this in place of `env.EMAIL_SENDER` (and its eight siblings). Nothing at the
7
+ * call site changes — `enqueueEmail` takes a `create({ id, params })` and does not care what is
8
+ * behind it — which is the whole reason the seam was one method to begin with. The address comes
9
+ * from `<STEM>_ORIGIN`, which the dev orchestrator exports for every member of the dev set, pinned
10
+ * at feature-create and stable for the life of the feature.
11
+ *
12
+ * ## Failures are the sibling's, and they say so
13
+ *
14
+ * A worker that is not up, a port nothing is listening on, a host that refuses the dispatch: every
15
+ * one of those is a hop into something this process does not control, so it is
16
+ * `core/upstream_failed` (502) or `core/upstream_timeout` (504) — never `core/internal`, which would
17
+ * send an operator to read *our* logs about *their* Worker (CLAUDE.md §Errors). The `action` names
18
+ * the capability and the origin, because "is the email host running?" is the next question and the
19
+ * terminal already knows the answer.
20
+ *
21
+ * The timeout is not decoration. `enqueue` awaits this call on a request path, and a sibling that
22
+ * accepts a connection and never answers would otherwise hold a sign-in open until the platform
23
+ * killed it. A timed-out dispatch is reported as one — separately from a failed one — because the
24
+ * instance may have started regardless, and the scheduler's re-drive asks that question of the
25
+ * batch id rather than assuming an answer.
26
+ */
27
+ /** How the dispatcher reaches the sibling. Structural, so a test hands over a plain function. */
28
+ export type LoopbackFetch = (url: string, init: RequestInit) => Promise<Response>;
29
+ /** What the dispatcher needs to stand in for one cross-script Workflow binding. */
30
+ export interface LoopbackWorkflowOptions {
31
+ /**
32
+ * The sibling worker's origin — `http://localhost:8797`, as `<STEM>_ORIGIN` carries it. A trailing
33
+ * slash is tolerated; nothing else about it is rewritten.
34
+ */
35
+ origin: string;
36
+ /** The Workflow binding to start on, named exactly as the host's own env binds it. */
37
+ binding: string;
38
+ /** The capability that owns the host. Named in the action line, so a failure says which worker. */
39
+ capability?: string;
40
+ /** The transport. Defaults to the runtime's `fetch`; injectable for tests. */
41
+ fetch?: LoopbackFetch;
42
+ /** How long to wait for the sibling. Defaults to 10 s — a local hop, so anything slower is stuck. */
43
+ timeoutMs?: number;
44
+ }
45
+ /**
46
+ * Build a {@link WorkflowBinding} that dispatches over loopback to a sibling worker's dispatch route.
47
+ *
48
+ * Returns the plain seam, so it drops into any env slot a cross-script binding occupied — including
49
+ * `@pithy-sh/email`'s narrower `SendWorkflowBinding`, which is a subtype of this one.
50
+ */
51
+ export declare function loopbackWorkflowBinding(options: LoopbackWorkflowOptions): WorkflowBinding;
52
+ //# sourceMappingURL=loopback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopback.d.ts","sourceRoot":"","sources":["../../src/workflow/loopback.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,iGAAiG;AACjG,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAElF,mFAAmF;AACnF,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAC;IAChB,mGAAmG;IACnG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,qGAAqG;IACrG,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAuBD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,uBAAuB,GAAG,eAAe,CAoEzF"}
@@ -0,0 +1,76 @@
1
+ import { UpstreamError, UpstreamTimeoutError } from "../error/pithyError.js";
2
+ import { workflowDispatchPath } from "./schemas.js";
3
+ //#region src/workflow/loopback.ts
4
+ /** 10 seconds. A loopback dispatch either lands immediately or is not going to. */
5
+ const DEFAULT_TIMEOUT_MS = 1e4;
6
+ /** How much of a failing answer's body is worth carrying into a log line. */
7
+ const BODY_SNIPPET = 300;
8
+ /** Whether a rejection is the deadline rather than the connection. */
9
+ function isTimeout(cause) {
10
+ const name = cause?.name;
11
+ return name === "TimeoutError" || name === "AbortError";
12
+ }
13
+ /** A short, safe rendering of a failing answer's body. Never thrown from — a failure is already in hand. */
14
+ async function bodySnippet(response) {
15
+ try {
16
+ return (await response.text()).slice(0, BODY_SNIPPET);
17
+ } catch {
18
+ return "<unreadable>";
19
+ }
20
+ }
21
+ /**
22
+ * Build a {@link WorkflowBinding} that dispatches over loopback to a sibling worker's dispatch route.
23
+ *
24
+ * Returns the plain seam, so it drops into any env slot a cross-script binding occupied — including
25
+ * `@pithy-sh/email`'s narrower `SendWorkflowBinding`, which is a subtype of this one.
26
+ */
27
+ function loopbackWorkflowBinding(options) {
28
+ const origin = options.origin.replace(/\/+$/, "");
29
+ const url = `${origin}${workflowDispatchPath(options.binding)}`;
30
+ const owner = options.capability ?? options.binding;
31
+ const send = options.fetch ?? ((target, init) => fetch(target, init));
32
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
33
+ const running = `Check that the ${owner} host is running under pithy dev at ${origin}.`;
34
+ return { async create(instance) {
35
+ const body = {
36
+ id: instance?.id,
37
+ params: instance?.params
38
+ };
39
+ let response;
40
+ try {
41
+ response = await send(url, {
42
+ method: "POST",
43
+ headers: { "content-type": "application/json" },
44
+ body: JSON.stringify(body),
45
+ signal: AbortSignal.timeout(timeoutMs)
46
+ });
47
+ } catch (cause) {
48
+ if (isTimeout(cause)) throw new UpstreamTimeoutError({
49
+ message: "The workflow host did not answer in time.",
50
+ action: running,
51
+ detail: `POST ${url} exceeded ${timeoutMs} ms.`
52
+ }, { cause });
53
+ throw new UpstreamError({
54
+ message: "The workflow host could not be reached.",
55
+ action: running,
56
+ detail: `POST ${url} failed: ${String(cause)}`
57
+ }, { cause });
58
+ }
59
+ if (!response.ok) throw new UpstreamError({
60
+ message: "The workflow host refused the dispatch.",
61
+ action: running,
62
+ detail: `POST ${url} answered ${response.status}. ${await bodySnippet(response)}`
63
+ });
64
+ try {
65
+ return await response.json();
66
+ } catch (cause) {
67
+ throw new UpstreamError({
68
+ message: "The workflow host answered something that is not a dispatch result.",
69
+ action: running,
70
+ detail: `POST ${url} answered ${response.status} with an unreadable body.`
71
+ }, { cause });
72
+ }
73
+ } };
74
+ }
75
+ //#endregion
76
+ export { loopbackWorkflowBinding };
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Every name a durable job answers to, in one module. The CLI writes these into a host worker's
3
+ * resolved `wrangler.jsonc`, the provisioner deploys under them, and the dispatcher resolves
4
+ * against them — so they are derived here once rather than formatted at three call sites that
5
+ * would drift.
6
+ *
7
+ * The shape is the project-scoped rule from `@pithy-sh/core/src/naming/resource`:
8
+ * **`<project>-<env>-<capability>`** for a host worker, and that plus `-<job>` for a Workflow.
9
+ * Worker script names and Workflow names are both **account-scoped** in Cloudflare, so without the
10
+ * project segment a second Pithy project's deploy does not share a name — it overwrites the first
11
+ * project's running Worker. The project segment is what makes two projects in one account possible.
12
+ *
13
+ * Renaming a Workflow orphans every instance running under the old name, so these names are a
14
+ * contract once anything is deployed. That is also why an over-long name is **refused rather than
15
+ * truncated** here: a Workflow whose name silently changed shape is worse than a build error
16
+ * telling you to shorten a capability name.
17
+ */
18
+ /**
19
+ * Cloudflare caps a Workflow name at 64 bytes.
20
+ *
21
+ * This is the number `WORKFLOW_DERIVED_PROJECT_NAME` comes from: a project is capped at whatever this
22
+ * leaves after the longest environment and the longest `<capability>-<job>`, so the refusal lands at
23
+ * `pithy init` rather than here, at the first deploy, with resources already provisioned.
24
+ * `naming.test.ts` pins the two together.
25
+ */
26
+ export declare const MAX_WORKFLOW_NAME_BYTES: 64;
27
+ /**
28
+ * A Worker script name is **63**, not 64 — a different resource with a different number.
29
+ *
30
+ * Cloudflare allows 255 in general and 63 once a workers.dev subdomain is on. Pithy holds the 63:
31
+ * it is the only value that stays true after an adopter enables workers.dev, and a script cannot be
32
+ * renamed once anything points at it. The one-character gap between this and
33
+ * {@link MAX_WORKFLOW_NAME_BYTES} is real; collapsing the two would loosen this one.
34
+ */
35
+ export declare const MAX_WORKER_NAME_BYTES: 63;
36
+ /** The identity of a capability's deployment in one environment. */
37
+ export interface WorkflowHostNameParts {
38
+ /** The project name — the root `pithy.config.ts` `name`, resolved by `requireProjectName` and never guessed. */
39
+ project: string;
40
+ /** The capability that owns the host worker (e.g. `email`). */
41
+ capability: string;
42
+ /** The deployment environment (e.g. `staging`). */
43
+ env: string;
44
+ }
45
+ /** The identity of one durable job's Workflow in one environment. */
46
+ export interface WorkflowScriptNameParts extends WorkflowHostNameParts {
47
+ /** The job within the capability (e.g. `send`). */
48
+ job: string;
49
+ }
50
+ /**
51
+ * The deployed name of one job's Workflow in one environment — `<project>-<env>-<capability>-<job>`,
52
+ * e.g. `acme-staging-media-image-to-text`. This is what the CLI writes as the `name` of a
53
+ * `workflows` entry, and what `CloudflareWorkflowsClient` addresses when triggering from outside
54
+ * the Worker.
55
+ *
56
+ * Takes an options object rather than positional arguments deliberately: every part is a `string`,
57
+ * so a swapped project and capability would type-check silently and deploy under a name teardown
58
+ * could never find again.
59
+ */
60
+ export declare function workflowScriptName(parts: WorkflowScriptNameParts): string;
61
+ /**
62
+ * The deployed name of a capability's prebuilt host worker in one environment —
63
+ * `<project>-<env>-<capability>`. Same options-object rationale as {@link workflowScriptName}.
64
+ *
65
+ * Held to {@link MAX_WORKER_NAME_BYTES}, one character tighter than the Workflow it hosts: this is a
66
+ * Worker script name, and a workers.dev subdomain caps those at 63.
67
+ */
68
+ export declare function workflowHostName(parts: WorkflowHostNameParts): string;
69
+ /**
70
+ * The dispatch key a caller passes to `c.var.workflows.trigger(...)` — `<capability>/<job>`.
71
+ * Namespaced by capability so two capabilities may each own a job called `sweep`.
72
+ *
73
+ * **Deliberately not project-scoped.** This keys the in-Worker registry, and a Worker only ever
74
+ * hosts one project's capabilities — adding the project would put a value every call site already
75
+ * knows into a string every call site would have to thread. It is a dispatch key, not a
76
+ * Cloudflare resource name, so it shares none of the account-flatness problem the names above have.
77
+ */
78
+ export declare function workflowKey(capability: string, job: string): string;
79
+ //# sourceMappingURL=naming.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../../src/workflow/naming.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,IAAsC,CAAC;AAE3E;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,IAAoC,CAAC;AAmEvE,oEAAoE;AACpE,MAAM,WAAW,qBAAqB;IACpC,gHAAgH;IAChH,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;CACb;AAED,qEAAqE;AACrE,MAAM,WAAW,uBAAwB,SAAQ,qBAAqB;IACpE,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,MAAM,CAKzE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAGrE;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAInE"}
@@ -0,0 +1,138 @@
1
+ import { NAME_SEGMENT } from "../naming/segment.js";
2
+ import { InternalError } from "../error/pithyError.js";
3
+ import { NAMESPACE_LIMITS } from "../naming/limits.js";
4
+ import { assertValidProjectName, kebab } from "../naming/resource.js";
5
+ //#region src/workflow/naming.ts
6
+ /**
7
+ * Every name a durable job answers to, in one module. The CLI writes these into a host worker's
8
+ * resolved `wrangler.jsonc`, the provisioner deploys under them, and the dispatcher resolves
9
+ * against them — so they are derived here once rather than formatted at three call sites that
10
+ * would drift.
11
+ *
12
+ * The shape is the project-scoped rule from `@pithy-sh/core/src/naming/resource`:
13
+ * **`<project>-<env>-<capability>`** for a host worker, and that plus `-<job>` for a Workflow.
14
+ * Worker script names and Workflow names are both **account-scoped** in Cloudflare, so without the
15
+ * project segment a second Pithy project's deploy does not share a name — it overwrites the first
16
+ * project's running Worker. The project segment is what makes two projects in one account possible.
17
+ *
18
+ * Renaming a Workflow orphans every instance running under the old name, so these names are a
19
+ * contract once anything is deployed. That is also why an over-long name is **refused rather than
20
+ * truncated** here: a Workflow whose name silently changed shape is worse than a build error
21
+ * telling you to shorten a capability name.
22
+ */
23
+ /**
24
+ * Cloudflare caps a Workflow name at 64 bytes.
25
+ *
26
+ * This is the number `WORKFLOW_DERIVED_PROJECT_NAME` comes from: a project is capped at whatever this
27
+ * leaves after the longest environment and the longest `<capability>-<job>`, so the refusal lands at
28
+ * `pithy init` rather than here, at the first deploy, with resources already provisioned.
29
+ * `naming.test.ts` pins the two together.
30
+ */
31
+ const MAX_WORKFLOW_NAME_BYTES = NAMESPACE_LIMITS.workflow.maxLength;
32
+ /**
33
+ * A Worker script name is **63**, not 64 — a different resource with a different number.
34
+ *
35
+ * Cloudflare allows 255 in general and 63 once a workers.dev subdomain is on. Pithy holds the 63:
36
+ * it is the only value that stays true after an adopter enables workers.dev, and a script cannot be
37
+ * renamed once anything points at it. The one-character gap between this and
38
+ * {@link MAX_WORKFLOW_NAME_BYTES} is real; collapsing the two would loosen this one.
39
+ */
40
+ const MAX_WORKER_NAME_BYTES = NAMESPACE_LIMITS.worker.maxLength;
41
+ /**
42
+ * Reject a segment that cannot legally appear in a Cloudflare resource name, attributed to its role.
43
+ *
44
+ * The shape is {@link NAME_SEGMENT}, the one segment rule — a Workflow name and a Worker script name
45
+ * accept exactly what every other composed name does, so this reads the rule rather than restating it.
46
+ */
47
+ function assertSegment(value, role) {
48
+ if (!NAME_SEGMENT.test(value)) throw new InternalError({
49
+ message: `Invalid ${role} "${value}" in a workflow name.`,
50
+ action: "Use lowercase letters, digits, and single hyphens, starting with a letter.",
51
+ detail: `A ${role} must match ${NAME_SEGMENT.source} to be a legal Cloudflare resource-name segment.`
52
+ });
53
+ }
54
+ /**
55
+ * Reject a composed name Cloudflare would refuse, naming the limit rather than letting the deploy fail.
56
+ *
57
+ * The limit is passed in because the two names this module composes have two different ones: a Workflow
58
+ * gets 64, the Worker script hosting it gets 63.
59
+ */
60
+ function assertLength(name, limit) {
61
+ if (new TextEncoder().encode(name).length > limit) throw new InternalError({
62
+ message: `The name "${name}" is longer than Cloudflare's ${limit}-byte limit.`,
63
+ action: "Shorten the project, capability, or job name."
64
+ });
65
+ return name;
66
+ }
67
+ /**
68
+ * Reject a `<capability>-<job>` tail longer than {@link MAX_CAPABILITY_JOB} — the tail
69
+ * `MAX_PROJECT_NAME` was derived against.
70
+ *
71
+ * The project cap is only true while no registry declares a longer tail than the longest one that
72
+ * existed when it was computed. A capability that would invalidate it fails here, at the name it
73
+ * would deploy under, rather than quietly shortening the project name every existing project was
74
+ * already accepted under — a change that cannot be made after the fact, because a project name is
75
+ * stable forever once anything is provisioned.
76
+ */
77
+ function assertCapabilityJob(capability, job) {
78
+ const tail = `${capability}-${job}`;
79
+ if (tail.length > 22) throw new InternalError({
80
+ message: `The job "${capability}/${job}" is ${tail.length} characters. A <capability>-<job> stops at 22.`,
81
+ action: "Shorten the capability or job name.",
82
+ detail: `MAX_PROJECT_NAME is derived against a 22-character tail. Raising MAX_CAPABILITY_JOB shortens every adopter's legal project name, and a provisioned project cannot be renamed.`
83
+ });
84
+ }
85
+ /**
86
+ * The `<project>-<env>` head every deployed name shares. The project is held to core's one project rule
87
+ * — charset *and* length — because it comes from the adopter's `pithy.config.ts` and is the one segment
88
+ * a human typed; the rest is author-controlled code and is asserted rather than mangled, so a bad
89
+ * capability name is a build error, not a surprise.
90
+ */
91
+ function head(project, env) {
92
+ assertValidProjectName(project);
93
+ assertSegment(env, "environment");
94
+ return `${kebab(project)}-${env}`;
95
+ }
96
+ /**
97
+ * The deployed name of one job's Workflow in one environment — `<project>-<env>-<capability>-<job>`,
98
+ * e.g. `acme-staging-media-image-to-text`. This is what the CLI writes as the `name` of a
99
+ * `workflows` entry, and what `CloudflareWorkflowsClient` addresses when triggering from outside
100
+ * the Worker.
101
+ *
102
+ * Takes an options object rather than positional arguments deliberately: every part is a `string`,
103
+ * so a swapped project and capability would type-check silently and deploy under a name teardown
104
+ * could never find again.
105
+ */
106
+ function workflowScriptName(parts) {
107
+ assertSegment(parts.capability, "capability");
108
+ assertSegment(parts.job, "job");
109
+ assertCapabilityJob(parts.capability, parts.job);
110
+ return assertLength(`${head(parts.project, parts.env)}-${parts.capability}-${parts.job}`, MAX_WORKFLOW_NAME_BYTES);
111
+ }
112
+ /**
113
+ * The deployed name of a capability's prebuilt host worker in one environment —
114
+ * `<project>-<env>-<capability>`. Same options-object rationale as {@link workflowScriptName}.
115
+ *
116
+ * Held to {@link MAX_WORKER_NAME_BYTES}, one character tighter than the Workflow it hosts: this is a
117
+ * Worker script name, and a workers.dev subdomain caps those at 63.
118
+ */
119
+ function workflowHostName(parts) {
120
+ assertSegment(parts.capability, "capability");
121
+ return assertLength(`${head(parts.project, parts.env)}-${parts.capability}`, MAX_WORKER_NAME_BYTES);
122
+ }
123
+ /**
124
+ * The dispatch key a caller passes to `c.var.workflows.trigger(...)` — `<capability>/<job>`.
125
+ * Namespaced by capability so two capabilities may each own a job called `sweep`.
126
+ *
127
+ * **Deliberately not project-scoped.** This keys the in-Worker registry, and a Worker only ever
128
+ * hosts one project's capabilities — adding the project would put a value every call site already
129
+ * knows into a string every call site would have to thread. It is a dispatch key, not a
130
+ * Cloudflare resource name, so it shares none of the account-flatness problem the names above have.
131
+ */
132
+ function workflowKey(capability, job) {
133
+ assertSegment(capability, "capability");
134
+ assertSegment(job, "job");
135
+ return `${capability}/${job}`;
136
+ }
137
+ //#endregion
138
+ export { MAX_WORKER_NAME_BYTES, MAX_WORKFLOW_NAME_BYTES, workflowHostName, workflowKey, workflowScriptName };
@@ -0,0 +1,19 @@
1
+ import type { Capability } from "../capability/capability";
2
+ import type { RegisteredWorkflow, WorkflowRegistry } from "./spec";
3
+ /**
4
+ * Registration: every capability's `workflows` map merged into one project-wide registry keyed
5
+ * `<capability>/<job>`. The peer of `composeDatabases` and `composeKv`, and deliberately simpler —
6
+ * a job belongs to exactly one capability, so there is no cross-capability merge to arbitrate,
7
+ * only a duplicate to reject.
8
+ */
9
+ /**
10
+ * Merge every capability's declared jobs into one registry. A capability declaring the same job
11
+ * name twice is impossible (it is a map key); two capabilities colliding is impossible (the key is
12
+ * capability-namespaced). What remains is one real conflict — the same capability `name` composed
13
+ * twice — which is an assembly-time author error, caught here rather than surfacing as a job that
14
+ * silently dispatches to the wrong binding.
15
+ */
16
+ export declare function composeWorkflows(capabilities: readonly Capability[]): WorkflowRegistry;
17
+ /** Every registered job carrying a cron — what `createEntrypoint` fires on a `scheduled` event. */
18
+ export declare function scheduledWorkflows(registry: WorkflowRegistry): RegisteredWorkflow[];
19
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/workflow/register.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAG3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAEnE;;;;;GAKG;AAEH;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,SAAS,UAAU,EAAE,GAAG,gBAAgB,CAgBtF;AAED,mGAAmG;AACnG,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,kBAAkB,EAAE,CAEnF"}
@@ -0,0 +1,40 @@
1
+ import { InternalError } from "../error/pithyError.js";
2
+ import { workflowKey } from "./naming.js";
3
+ //#region src/workflow/register.ts
4
+ /**
5
+ * Registration: every capability's `workflows` map merged into one project-wide registry keyed
6
+ * `<capability>/<job>`. The peer of `composeDatabases` and `composeKv`, and deliberately simpler —
7
+ * a job belongs to exactly one capability, so there is no cross-capability merge to arbitrate,
8
+ * only a duplicate to reject.
9
+ */
10
+ /**
11
+ * Merge every capability's declared jobs into one registry. A capability declaring the same job
12
+ * name twice is impossible (it is a map key); two capabilities colliding is impossible (the key is
13
+ * capability-namespaced). What remains is one real conflict — the same capability `name` composed
14
+ * twice — which is an assembly-time author error, caught here rather than surfacing as a job that
15
+ * silently dispatches to the wrong binding.
16
+ */
17
+ function composeWorkflows(capabilities) {
18
+ const registry = {};
19
+ for (const capability of capabilities) for (const [job, spec] of Object.entries(capability.workflows ?? {})) {
20
+ const key = workflowKey(capability.name, job);
21
+ if (key in registry) throw new InternalError({
22
+ message: `Duplicate workflow "${key}".`,
23
+ action: "Compose each capability once — two capabilities are registering the same name.",
24
+ detail: `The capability "${capability.name}" is composed more than once, or two capabilities share the name.`
25
+ });
26
+ registry[key] = {
27
+ key,
28
+ capability: capability.name,
29
+ job,
30
+ spec
31
+ };
32
+ }
33
+ return registry;
34
+ }
35
+ /** Every registered job carrying a cron — what `createEntrypoint` fires on a `scheduled` event. */
36
+ function scheduledWorkflows(registry) {
37
+ return Object.values(registry).filter((entry) => entry.spec.schedule !== void 0);
38
+ }
39
+ //#endregion
40
+ export { composeWorkflows, scheduledWorkflows };
@@ -0,0 +1,44 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * The request and response contract of the host's dispatch route ({@link ./dispatchRoute.ts}).
4
+ *
5
+ * Declared here rather than on the route line for the reason every capability's `http/schemas.ts`
6
+ * exists (CLAUDE.md §HTTP): the route declares *that* it validates, this declares *what*, and the
7
+ * loopback dispatcher on the other end of the wire builds its body against the same object.
8
+ *
9
+ * **The path is here too, and that is deliberate.** An address is as much of the wire contract as a
10
+ * body is, and putting it beside the route would make the dispatcher import the route module to know
11
+ * where to POST — which is the module that imports the dispatcher to resolve a binding. One import
12
+ * cycle, for a template string neither end owns more than the other.
13
+ */
14
+ /** The reserved namespace the host's dispatch route lives under, beside `/__pithy/dev-login`. */
15
+ export declare const WORKFLOW_DISPATCH_BASE = "/__pithy/workflows";
16
+ /** The registered path pattern. `:binding` is the host's own Workflow binding name. */
17
+ export declare const WORKFLOW_DISPATCH_ROUTE = "/__pithy/workflows/:binding";
18
+ /** The concrete path for one binding — what the loopback dispatcher POSTs to. */
19
+ export declare function workflowDispatchPath(binding: string): string;
20
+ /** The path segment naming which of the host's own Workflow bindings to start an instance on. */
21
+ export declare const WorkflowDispatchParams: z.ZodObject<{
22
+ binding: z.ZodString;
23
+ }, z.core.$strip>;
24
+ export type WorkflowDispatchParams = z.infer<typeof WorkflowDispatchParams>;
25
+ /** The body: the instance id and the payload, exactly as `create({ id, params })` takes them. */
26
+ export declare const WorkflowDispatchRequest: z.ZodObject<{
27
+ id: z.ZodOptional<z.ZodString>;
28
+ params: z.ZodUnknown;
29
+ }, z.core.$strip>;
30
+ export type WorkflowDispatchRequest = z.infer<typeof WorkflowDispatchRequest>;
31
+ /**
32
+ * The answer: which binding was started, under which id.
33
+ *
34
+ * A response object rather than an interface, for the reason every admin response is one (CLAUDE.md
35
+ * §HTTP): the caller is across a process boundary, and a TypeScript interface is erased before it can
36
+ * help. Nothing here carries a codec — an answer must parse back to exactly what went in.
37
+ */
38
+ export declare const WorkflowDispatchResponse: z.ZodObject<{
39
+ binding: z.ZodString;
40
+ id: z.ZodOptional<z.ZodString>;
41
+ started: z.ZodLiteral<true>;
42
+ }, z.core.$strip>;
43
+ export type WorkflowDispatchResponse = z.infer<typeof WorkflowDispatchResponse>;
44
+ //# sourceMappingURL=schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/workflow/schemas.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;GAWG;AAEH,iGAAiG;AACjG,eAAO,MAAM,sBAAsB,uBAAuB,CAAC;AAE3D,uFAAuF;AACvF,eAAO,MAAM,uBAAuB,gCAAuC,CAAC;AAE5E,iFAAiF;AACjF,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,iGAAiG;AACjG,eAAO,MAAM,sBAAsB;;iBAc2B,CAAC;AAC/D,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE5E,iGAAiG;AACjG,eAAO,MAAM,uBAAuB;;;iBAgByC,CAAC;AAC9E,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAE9E;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB;;;;iBAQgC,CAAC;AACtE,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC"}