@beignet/core 0.0.3 → 0.0.5

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 (360) hide show
  1. package/CHANGELOG.md +159 -0
  2. package/README.md +792 -50
  3. package/dist/application/index.d.ts +28 -2
  4. package/dist/application/index.d.ts.map +1 -1
  5. package/dist/application/index.js +140 -12
  6. package/dist/application/index.js.map +1 -1
  7. package/dist/client/client.d.ts +2 -2
  8. package/dist/client/client.d.ts.map +1 -1
  9. package/dist/client/client.js +136 -48
  10. package/dist/client/client.js.map +1 -1
  11. package/dist/client/error-messages.d.ts +14 -0
  12. package/dist/client/error-messages.d.ts.map +1 -0
  13. package/dist/client/error-messages.js +23 -0
  14. package/dist/client/error-messages.js.map +1 -0
  15. package/dist/client/index.d.ts +8 -4
  16. package/dist/client/index.d.ts.map +1 -1
  17. package/dist/client/index.js +6 -2
  18. package/dist/client/index.js.map +1 -1
  19. package/dist/client/types.d.ts +35 -5
  20. package/dist/client/types.d.ts.map +1 -1
  21. package/dist/client-only.d.ts +8 -0
  22. package/dist/client-only.d.ts.map +1 -0
  23. package/dist/client-only.js +8 -0
  24. package/dist/client-only.js.map +1 -0
  25. package/dist/config/index.d.ts +5 -5
  26. package/dist/config/index.d.ts.map +1 -1
  27. package/dist/config/index.js +2 -2
  28. package/dist/config/index.js.map +1 -1
  29. package/dist/contracts/catalog-errors.d.ts +27 -0
  30. package/dist/contracts/catalog-errors.d.ts.map +1 -0
  31. package/dist/contracts/catalog-errors.js +69 -0
  32. package/dist/contracts/catalog-errors.js.map +1 -0
  33. package/dist/contracts/contract-builder.d.ts +15 -12
  34. package/dist/contracts/contract-builder.d.ts.map +1 -1
  35. package/dist/contracts/contract-builder.js +15 -41
  36. package/dist/contracts/contract-builder.js.map +1 -1
  37. package/dist/contracts/contract-group.d.ts +11 -8
  38. package/dist/contracts/contract-group.d.ts.map +1 -1
  39. package/dist/contracts/contract-group.js +13 -40
  40. package/dist/contracts/contract-group.js.map +1 -1
  41. package/dist/contracts/contract-like.d.ts +1 -1
  42. package/dist/contracts/contract-like.d.ts.map +1 -1
  43. package/dist/contracts/index.d.ts +13 -9
  44. package/dist/contracts/index.d.ts.map +1 -1
  45. package/dist/contracts/index.js +9 -5
  46. package/dist/contracts/index.js.map +1 -1
  47. package/dist/contracts/openapi-meta.d.ts +48 -0
  48. package/dist/contracts/openapi-meta.d.ts.map +1 -1
  49. package/dist/contracts/openapi-meta.js +3 -0
  50. package/dist/contracts/openapi-meta.js.map +1 -1
  51. package/dist/contracts/path-template.d.ts +1 -1
  52. package/dist/contracts/path-template.js +2 -2
  53. package/dist/contracts/path-template.js.map +1 -1
  54. package/dist/contracts/schema-shape.d.ts +37 -0
  55. package/dist/contracts/schema-shape.d.ts.map +1 -0
  56. package/dist/contracts/schema-shape.js +61 -0
  57. package/dist/contracts/schema-shape.js.map +1 -0
  58. package/dist/contracts/success-status.d.ts +32 -0
  59. package/dist/contracts/success-status.d.ts.map +1 -0
  60. package/dist/contracts/success-status.js +18 -0
  61. package/dist/contracts/success-status.js.map +1 -0
  62. package/dist/contracts/types.d.ts +25 -5
  63. package/dist/contracts/types.d.ts.map +1 -1
  64. package/dist/contracts/types.js.map +1 -1
  65. package/dist/contracts/utils.d.ts +1 -1
  66. package/dist/contracts/utils.d.ts.map +1 -1
  67. package/dist/contracts/utils.js +1 -1
  68. package/dist/contracts/utils.js.map +1 -1
  69. package/dist/domain/events.d.ts +1 -1
  70. package/dist/domain/events.d.ts.map +1 -1
  71. package/dist/domain/events.js +1 -1
  72. package/dist/domain/events.js.map +1 -1
  73. package/dist/domain/index.d.ts +3 -3
  74. package/dist/domain/index.d.ts.map +1 -1
  75. package/dist/domain/index.js +3 -3
  76. package/dist/domain/index.js.map +1 -1
  77. package/dist/errors/catalog.d.ts +9 -1
  78. package/dist/errors/catalog.d.ts.map +1 -1
  79. package/dist/errors/catalog.js +7 -1
  80. package/dist/errors/catalog.js.map +1 -1
  81. package/dist/errors/http.d.ts +10 -0
  82. package/dist/errors/http.d.ts.map +1 -1
  83. package/dist/errors/http.js +11 -1
  84. package/dist/errors/http.js.map +1 -1
  85. package/dist/errors/index.d.ts +4 -4
  86. package/dist/errors/index.d.ts.map +1 -1
  87. package/dist/errors/index.js +4 -4
  88. package/dist/errors/index.js.map +1 -1
  89. package/dist/errors/response.d.ts +4 -1
  90. package/dist/errors/response.d.ts.map +1 -1
  91. package/dist/errors/response.js.map +1 -1
  92. package/dist/events/index.d.ts +10 -12
  93. package/dist/events/index.d.ts.map +1 -1
  94. package/dist/events/index.js +10 -10
  95. package/dist/events/index.js.map +1 -1
  96. package/dist/idempotency/index.d.ts +5 -3
  97. package/dist/idempotency/index.d.ts.map +1 -1
  98. package/dist/idempotency/index.js.map +1 -1
  99. package/dist/jobs/index.d.ts +12 -14
  100. package/dist/jobs/index.d.ts.map +1 -1
  101. package/dist/jobs/index.js +13 -13
  102. package/dist/jobs/index.js.map +1 -1
  103. package/dist/notifications/index.d.ts +14 -16
  104. package/dist/notifications/index.d.ts.map +1 -1
  105. package/dist/notifications/index.js +14 -14
  106. package/dist/notifications/index.js.map +1 -1
  107. package/dist/openapi/index.d.ts +8 -3
  108. package/dist/openapi/index.d.ts.map +1 -1
  109. package/dist/openapi/index.js +41 -29
  110. package/dist/openapi/index.js.map +1 -1
  111. package/dist/openapi/schema-introspector.d.ts +37 -0
  112. package/dist/openapi/schema-introspector.d.ts.map +1 -1
  113. package/dist/openapi/schema-introspector.js +23 -17
  114. package/dist/openapi/schema-introspector.js.map +1 -1
  115. package/dist/outbox/index.d.ts +15 -6
  116. package/dist/outbox/index.d.ts.map +1 -1
  117. package/dist/outbox/index.js +60 -16
  118. package/dist/outbox/index.js.map +1 -1
  119. package/dist/ports/audit.d.ts +56 -10
  120. package/dist/ports/audit.d.ts.map +1 -1
  121. package/dist/ports/audit.js +71 -3
  122. package/dist/ports/audit.js.map +1 -1
  123. package/dist/ports/auth.d.ts +92 -0
  124. package/dist/ports/auth.d.ts.map +1 -1
  125. package/dist/ports/auth.js +92 -0
  126. package/dist/ports/auth.js.map +1 -1
  127. package/dist/ports/events.d.ts +2 -2
  128. package/dist/ports/events.d.ts.map +1 -1
  129. package/dist/ports/index.d.ts +62 -33
  130. package/dist/ports/index.d.ts.map +1 -1
  131. package/dist/ports/index.js +28 -34
  132. package/dist/ports/index.js.map +1 -1
  133. package/dist/ports/policy.d.ts +32 -3
  134. package/dist/ports/policy.d.ts.map +1 -1
  135. package/dist/ports/policy.js +13 -2
  136. package/dist/ports/policy.js.map +1 -1
  137. package/dist/ports/testing.d.ts +1030 -2
  138. package/dist/ports/testing.d.ts.map +1 -1
  139. package/dist/ports/testing.js +1031 -1
  140. package/dist/ports/testing.js.map +1 -1
  141. package/dist/ports/unbound.d.ts +21 -0
  142. package/dist/ports/unbound.d.ts.map +1 -0
  143. package/dist/ports/unbound.js +57 -0
  144. package/dist/ports/unbound.js.map +1 -0
  145. package/dist/ports/unit-of-work.d.ts +1 -1
  146. package/dist/ports/unit-of-work.d.ts.map +1 -1
  147. package/dist/ports/unit-of-work.js +1 -1
  148. package/dist/ports/unit-of-work.js.map +1 -1
  149. package/dist/providers/index.d.ts +3 -2
  150. package/dist/providers/index.d.ts.map +1 -1
  151. package/dist/providers/index.js +3 -2
  152. package/dist/providers/index.js.map +1 -1
  153. package/dist/providers/instrumentation.d.ts +45 -4
  154. package/dist/providers/instrumentation.d.ts.map +1 -1
  155. package/dist/providers/instrumentation.js +25 -6
  156. package/dist/providers/instrumentation.js.map +1 -1
  157. package/dist/providers/metadata.d.ts +39 -0
  158. package/dist/providers/metadata.d.ts.map +1 -0
  159. package/dist/providers/metadata.js +169 -0
  160. package/dist/providers/metadata.js.map +1 -0
  161. package/dist/providers/provider.d.ts +114 -9
  162. package/dist/providers/provider.d.ts.map +1 -1
  163. package/dist/providers/provider.js +3 -20
  164. package/dist/providers/provider.js.map +1 -1
  165. package/dist/schedules/index.d.ts +94 -13
  166. package/dist/schedules/index.d.ts.map +1 -1
  167. package/dist/schedules/index.js +66 -12
  168. package/dist/schedules/index.js.map +1 -1
  169. package/dist/server/audit-context.d.ts +29 -0
  170. package/dist/server/audit-context.d.ts.map +1 -0
  171. package/dist/server/audit-context.js +44 -0
  172. package/dist/server/audit-context.js.map +1 -0
  173. package/dist/server/context.d.ts +141 -0
  174. package/dist/server/context.d.ts.map +1 -0
  175. package/dist/server/context.js +39 -0
  176. package/dist/server/context.js.map +1 -0
  177. package/dist/server/contract-like.d.ts +1 -1
  178. package/dist/server/contract-like.d.ts.map +1 -1
  179. package/dist/server/contract-like.js +1 -1
  180. package/dist/server/contract-like.js.map +1 -1
  181. package/dist/server/health.d.ts +2 -2
  182. package/dist/server/health.d.ts.map +1 -1
  183. package/dist/server/hooks/auth.d.ts +49 -10
  184. package/dist/server/hooks/auth.d.ts.map +1 -1
  185. package/dist/server/hooks/auth.js +77 -37
  186. package/dist/server/hooks/auth.js.map +1 -1
  187. package/dist/server/hooks/cors.d.ts +1 -1
  188. package/dist/server/hooks/cors.d.ts.map +1 -1
  189. package/dist/server/hooks/errors.d.ts +2 -2
  190. package/dist/server/hooks/errors.d.ts.map +1 -1
  191. package/dist/server/hooks/errors.js +2 -2
  192. package/dist/server/hooks/errors.js.map +1 -1
  193. package/dist/server/hooks/idempotency.d.ts +78 -0
  194. package/dist/server/hooks/idempotency.d.ts.map +1 -0
  195. package/dist/server/hooks/idempotency.js +154 -0
  196. package/dist/server/hooks/idempotency.js.map +1 -0
  197. package/dist/server/hooks/index.d.ts +8 -7
  198. package/dist/server/hooks/index.d.ts.map +1 -1
  199. package/dist/server/hooks/index.js +6 -5
  200. package/dist/server/hooks/index.js.map +1 -1
  201. package/dist/server/hooks/logging.d.ts +2 -2
  202. package/dist/server/hooks/logging.d.ts.map +1 -1
  203. package/dist/server/hooks/logging.js +1 -1
  204. package/dist/server/hooks/logging.js.map +1 -1
  205. package/dist/server/hooks/rate-limit.d.ts +25 -7
  206. package/dist/server/hooks/rate-limit.d.ts.map +1 -1
  207. package/dist/server/hooks/rate-limit.js +47 -12
  208. package/dist/server/hooks/rate-limit.js.map +1 -1
  209. package/dist/server/hooks.d.ts +1 -1
  210. package/dist/server/hooks.d.ts.map +1 -1
  211. package/dist/server/hooks.js +1 -1
  212. package/dist/server/hooks.js.map +1 -1
  213. package/dist/server/http.d.ts +61 -35
  214. package/dist/server/http.d.ts.map +1 -1
  215. package/dist/server/http.js +1 -20
  216. package/dist/server/http.js.map +1 -1
  217. package/dist/server/index.d.ts +36 -12
  218. package/dist/server/index.d.ts.map +1 -1
  219. package/dist/server/index.js +24 -8
  220. package/dist/server/index.js.map +1 -1
  221. package/dist/server/instrumentation.d.ts +108 -0
  222. package/dist/server/instrumentation.d.ts.map +1 -0
  223. package/dist/server/instrumentation.js +297 -0
  224. package/dist/server/instrumentation.js.map +1 -0
  225. package/dist/server/openapi.d.ts +3 -3
  226. package/dist/server/openapi.d.ts.map +1 -1
  227. package/dist/server/openapi.js +1 -1
  228. package/dist/server/openapi.js.map +1 -1
  229. package/dist/server/providers/index.d.ts +3 -3
  230. package/dist/server/providers/index.d.ts.map +1 -1
  231. package/dist/server/providers/index.js +3 -3
  232. package/dist/server/providers/index.js.map +1 -1
  233. package/dist/server/providers/loadProviderConfig.d.ts +2 -2
  234. package/dist/server/providers/loadProviderConfig.d.ts.map +1 -1
  235. package/dist/server/providers/loadProviderConfig.js +2 -2
  236. package/dist/server/providers/loadProviderConfig.js.map +1 -1
  237. package/dist/server/request-context.d.ts +67 -0
  238. package/dist/server/request-context.d.ts.map +1 -0
  239. package/dist/server/request-context.js +79 -0
  240. package/dist/server/request-context.js.map +1 -0
  241. package/dist/server/server-context.d.ts +38 -0
  242. package/dist/server/server-context.d.ts.map +1 -0
  243. package/dist/server/server-context.js +38 -0
  244. package/dist/server/server-context.js.map +1 -0
  245. package/dist/server/server.d.ts +105 -33
  246. package/dist/server/server.d.ts.map +1 -1
  247. package/dist/server/server.js +434 -118
  248. package/dist/server/server.js.map +1 -1
  249. package/dist/server/types.d.ts +2 -2
  250. package/dist/server/types.d.ts.map +1 -1
  251. package/dist/server/types.js +2 -2
  252. package/dist/server/types.js.map +1 -1
  253. package/dist/server/use-case-route.d.ts +263 -0
  254. package/dist/server/use-case-route.d.ts.map +1 -0
  255. package/dist/server/use-case-route.js +77 -0
  256. package/dist/server/use-case-route.js.map +1 -0
  257. package/dist/server-only.d.ts +8 -0
  258. package/dist/server-only.d.ts.map +1 -0
  259. package/dist/server-only.js +8 -0
  260. package/dist/server-only.js.map +1 -0
  261. package/dist/tasks/index.d.ts +139 -0
  262. package/dist/tasks/index.d.ts.map +1 -0
  263. package/dist/tasks/index.js +98 -0
  264. package/dist/tasks/index.js.map +1 -0
  265. package/dist/testing/index.d.ts +607 -5
  266. package/dist/testing/index.d.ts.map +1 -1
  267. package/dist/testing/index.js +426 -4
  268. package/dist/testing/index.js.map +1 -1
  269. package/dist/tracing/index.d.ts +89 -0
  270. package/dist/tracing/index.d.ts.map +1 -0
  271. package/dist/tracing/index.js +101 -0
  272. package/dist/tracing/index.js.map +1 -0
  273. package/dist/uploads/client.d.ts +1 -1
  274. package/dist/uploads/client.d.ts.map +1 -1
  275. package/dist/uploads/index.d.ts +2 -2
  276. package/dist/uploads/index.d.ts.map +1 -1
  277. package/dist/uploads/index.js +1 -1
  278. package/dist/uploads/index.js.map +1 -1
  279. package/package.json +24 -2
  280. package/src/application/index.ts +193 -10
  281. package/src/client/client.ts +148 -150
  282. package/src/client/error-messages.ts +35 -0
  283. package/src/client/index.ts +12 -4
  284. package/src/client/types.ts +44 -5
  285. package/src/client-only.ts +7 -0
  286. package/src/config/index.ts +6 -6
  287. package/src/contracts/catalog-errors.ts +115 -0
  288. package/src/contracts/contract-builder.ts +39 -76
  289. package/src/contracts/contract-group.ts +33 -68
  290. package/src/contracts/contract-like.ts +1 -1
  291. package/src/contracts/index.ts +24 -11
  292. package/src/contracts/openapi-meta.ts +55 -0
  293. package/src/contracts/path-template.ts +2 -2
  294. package/src/contracts/schema-shape.ts +75 -0
  295. package/src/contracts/success-status.ts +68 -0
  296. package/src/contracts/types.ts +32 -5
  297. package/src/contracts/utils.ts +5 -2
  298. package/src/domain/events.ts +6 -2
  299. package/src/domain/index.ts +3 -3
  300. package/src/errors/catalog.ts +9 -1
  301. package/src/errors/http.ts +11 -1
  302. package/src/errors/index.ts +4 -4
  303. package/src/errors/response.ts +4 -1
  304. package/src/events/index.ts +12 -26
  305. package/src/idempotency/index.ts +5 -3
  306. package/src/jobs/index.ts +14 -24
  307. package/src/notifications/index.ts +17 -27
  308. package/src/openapi/index.ts +73 -38
  309. package/src/openapi/schema-introspector.ts +68 -17
  310. package/src/outbox/index.ts +84 -19
  311. package/src/ports/audit.ts +120 -11
  312. package/src/ports/auth.ts +132 -0
  313. package/src/ports/events.ts +2 -2
  314. package/src/ports/index.ts +104 -35
  315. package/src/ports/policy.ts +50 -3
  316. package/src/ports/testing.ts +2220 -33
  317. package/src/ports/unbound.ts +64 -0
  318. package/src/ports/unit-of-work.ts +6 -2
  319. package/src/providers/index.ts +16 -3
  320. package/src/providers/instrumentation.ts +86 -7
  321. package/src/providers/metadata.ts +234 -0
  322. package/src/providers/provider.ts +168 -9
  323. package/src/schedules/index.ts +173 -23
  324. package/src/server/audit-context.ts +45 -0
  325. package/src/server/context.ts +224 -0
  326. package/src/server/contract-like.ts +1 -1
  327. package/src/server/health.ts +2 -2
  328. package/src/server/hooks/auth.ts +141 -51
  329. package/src/server/hooks/cors.ts +1 -1
  330. package/src/server/hooks/errors.ts +7 -4
  331. package/src/server/hooks/idempotency.ts +263 -0
  332. package/src/server/hooks/index.ts +14 -7
  333. package/src/server/hooks/logging.ts +3 -3
  334. package/src/server/hooks/rate-limit.ts +85 -17
  335. package/src/server/hooks.ts +1 -1
  336. package/src/server/http.ts +78 -51
  337. package/src/server/index.ts +62 -12
  338. package/src/server/instrumentation.ts +470 -0
  339. package/src/server/openapi.ts +4 -4
  340. package/src/server/providers/index.ts +6 -3
  341. package/src/server/providers/loadProviderConfig.ts +4 -4
  342. package/src/server/request-context.ts +116 -0
  343. package/src/server/server-context.ts +44 -0
  344. package/src/server/server.ts +886 -238
  345. package/src/server/types.ts +2 -2
  346. package/src/server/use-case-route.ts +430 -0
  347. package/src/server-only.ts +7 -0
  348. package/src/tasks/index.ts +275 -0
  349. package/src/testing/index.ts +1142 -6
  350. package/src/tracing/index.ts +176 -0
  351. package/src/uploads/client.ts +1 -1
  352. package/src/uploads/index.ts +7 -3
  353. package/dist/ports/mailer.d.ts +0 -6
  354. package/dist/ports/mailer.d.ts.map +0 -1
  355. package/dist/ports/mailer.js +0 -2
  356. package/dist/ports/mailer.js.map +0 -1
  357. package/dist/ports/schedules.d.ts +0 -9
  358. package/dist/ports/schedules.d.ts.map +0 -1
  359. package/dist/ports/schedules.js +0 -2
  360. package/dist/ports/schedules.js.map +0 -1
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Unbound port placeholders for deferred `definePorts(...)` keys.
3
+ *
4
+ * Ports declared as deferred boot as marked placeholders. Any method call on
5
+ * a placeholder throws a descriptive error, and `createServer(...)` scans
6
+ * final ports after provider startup so a missing provider fails boot instead
7
+ * of failing on first use.
8
+ */
9
+
10
+ const UNBOUND_PORT_MARKER = Symbol.for("beignet.unboundPort");
11
+
12
+ function unboundPortMessage(portName: string): string {
13
+ return (
14
+ `Port "${portName}" is not bound. "${portName}" is declared as deferred ` +
15
+ "in definePorts(...). Register a provider that contributes it " +
16
+ "(server/providers.ts) or bind it in infra/app-ports.ts."
17
+ );
18
+ }
19
+
20
+ /**
21
+ * Create a marked placeholder for a deferred port.
22
+ *
23
+ * Property access returns a function that throws, so calling any method on an
24
+ * unbound port produces a descriptive error naming the port.
25
+ */
26
+ export function createUnboundPort(portName: string): unknown {
27
+ return new Proxy(
28
+ {},
29
+ {
30
+ get(_target, property) {
31
+ if (property === UNBOUND_PORT_MARKER) return true;
32
+ if (property === Symbol.toStringTag) {
33
+ return `UnboundPort(${portName})`;
34
+ }
35
+ // Keep unbound ports safe to `await` and JSON-serialize.
36
+ if (property === "then" || property === "toJSON") return undefined;
37
+ if (typeof property === "symbol") return undefined;
38
+ if (property === "toString") {
39
+ return () => `[unbound port "${portName}"]`;
40
+ }
41
+
42
+ return () => {
43
+ throw new Error(unboundPortMessage(portName));
44
+ };
45
+ },
46
+ },
47
+ );
48
+ }
49
+
50
+ /**
51
+ * Check whether a value is an unbound port placeholder created for a deferred
52
+ * `definePorts(...)` key.
53
+ */
54
+ export function isUnboundPort(value: unknown): boolean {
55
+ if (value === null || typeof value !== "object") return false;
56
+
57
+ try {
58
+ return (
59
+ (value as Record<PropertyKey, unknown>)[UNBOUND_PORT_MARKER] === true
60
+ );
61
+ } catch {
62
+ return false;
63
+ }
64
+ }
@@ -1,5 +1,9 @@
1
- import { parseEventPayload } from "../events";
2
- import type { DomainEventDef, EventBusPort, InferEventPayload } from "./events";
1
+ import { parseEventPayload } from "../events/index.js";
2
+ import type {
3
+ DomainEventDef,
4
+ EventBusPort,
5
+ InferEventPayload,
6
+ } from "./events.js";
3
7
 
4
8
  type MaybePromise<T> = T | Promise<T>;
5
9
 
@@ -13,6 +13,7 @@ export {
13
13
  isProviderInstrumentation,
14
14
  isProviderInstrumentationPort,
15
15
  type JobProviderInstrumentationEvent,
16
+ type OutboxProviderInstrumentationEvent,
16
17
  type ProviderCustomInstrumentationEventInput,
17
18
  type ProviderInstrumentation,
18
19
  type ProviderInstrumentationEvent,
@@ -26,15 +27,27 @@ export {
26
27
  resolveProviderInstrumentationPort,
27
28
  type ScheduleProviderInstrumentationEvent,
28
29
  type UseCaseProviderInstrumentationEvent,
29
- } from "./instrumentation";
30
+ } from "./instrumentation.js";
30
31
  export {
32
+ type ProviderPackageMetadata,
33
+ type ProviderPackageMetadataIssue,
34
+ type ProviderPackageMetadataParseResult,
35
+ type ProviderPackagePortMetadata,
36
+ type ProviderPackageRegistrationMetadata,
37
+ type ProviderPackageRegistrationSeverity,
38
+ parseProviderPackageMetadata,
39
+ } from "./metadata.js";
40
+ export {
41
+ type AnyServiceProvider,
31
42
  createProvider,
32
43
  type InferOutput,
44
+ type InferProviderPorts,
33
45
  type MaybePromise,
34
46
  type ProvidedPortsOf,
35
- type ProvidedPortsOfList,
36
47
  type ProviderConfigDef,
37
48
  type ProviderLifecycleContext,
49
+ type ProviderServiceContextFactory,
38
50
  type ProviderSetupResult,
39
51
  type ServiceProvider,
40
- } from "./provider";
52
+ type ServiceProviderMetadata,
53
+ } from "./provider.js";
@@ -1,4 +1,4 @@
1
- import { type Redactor, redactValue } from "../ports/redaction";
1
+ import { type Redactor, redactValue } from "../ports/redaction.js";
2
2
 
3
3
  /**
4
4
  * Logical provider watcher name used to toggle groups of instrumentation
@@ -68,6 +68,10 @@ export interface RequestProviderInstrumentationEvent
68
68
  * Matched contract name, when known.
69
69
  */
70
70
  contractName?: string;
71
+ /**
72
+ * Which layer produced the response.
73
+ */
74
+ responseOwner?: "route" | "framework" | "transport" | "unknown";
71
75
  /**
72
76
  * Response status code.
73
77
  */
@@ -104,6 +108,19 @@ export interface ErrorProviderInstrumentationEvent
104
108
  * Use case associated with the error.
105
109
  */
106
110
  useCaseName?: string;
111
+ /**
112
+ * Which layer owns the error.
113
+ */
114
+ owner?:
115
+ | "route"
116
+ | "framework"
117
+ | "provider"
118
+ | "job"
119
+ | "schedule"
120
+ | "outbox"
121
+ | "client"
122
+ | "devtools"
123
+ | "unknown";
107
124
  }
108
125
 
109
126
  /**
@@ -169,7 +186,31 @@ export interface JobProviderInstrumentationEvent
169
186
  }
170
187
 
171
188
  /**
172
- * Scheduled task instrumentation.
189
+ * Durable outbox delivery instrumentation.
190
+ */
191
+ export interface OutboxProviderInstrumentationEvent
192
+ extends BaseProviderInstrumentationEvent {
193
+ type: "outbox";
194
+ /**
195
+ * Durable outbox message ID.
196
+ */
197
+ messageId: string;
198
+ /**
199
+ * Message kind.
200
+ */
201
+ messageKind: "event" | "job";
202
+ /**
203
+ * Event or job name stored in the outbox message.
204
+ */
205
+ messageName: string;
206
+ /**
207
+ * Delivery lifecycle status.
208
+ */
209
+ status: "delivered" | "retryScheduled" | "deadLettered";
210
+ }
211
+
212
+ /**
213
+ * Schedule instrumentation.
173
214
  */
174
215
  export interface ScheduleProviderInstrumentationEvent
175
216
  extends BaseProviderInstrumentationEvent {
@@ -237,6 +278,7 @@ export type ProviderInstrumentationEvent =
237
278
  | UseCaseProviderInstrumentationEvent
238
279
  | EventBusProviderInstrumentationEvent
239
280
  | JobProviderInstrumentationEvent
281
+ | OutboxProviderInstrumentationEvent
240
282
  | ScheduleProviderInstrumentationEvent
241
283
  | ProviderLifecycleInstrumentationEvent
242
284
  | CustomProviderInstrumentationEvent;
@@ -316,6 +358,10 @@ export interface ProviderInstrumentation {
316
358
 
317
359
  /**
318
360
  * Values accepted by `createProviderInstrumentation(...)`.
361
+ *
362
+ * Plain ports objects are accepted so callers can pass `ctx.ports` (or a
363
+ * provider's `ports` argument) directly; the resolver reads
364
+ * `ports.instrumentation`, then `ports.devtools`.
319
365
  */
320
366
  export type ProviderInstrumentationTarget =
321
367
  | ProviderInstrumentationPort
@@ -324,6 +370,7 @@ export type ProviderInstrumentationTarget =
324
370
  devtools?: ProviderInstrumentationPort | ProviderInstrumentation;
325
371
  instrumentation?: ProviderInstrumentationPort | ProviderInstrumentation;
326
372
  }
373
+ | Record<string, unknown>
327
374
  | undefined;
328
375
 
329
376
  function isObject(value: unknown): value is Record<string, unknown> {
@@ -332,12 +379,19 @@ function isObject(value: unknown): value is Record<string, unknown> {
332
379
 
333
380
  /**
334
381
  * Return whether a value is a provider instrumentation helper.
382
+ *
383
+ * Checks key presence with `in` before reading so probing proxy-backed
384
+ * objects, such as test-context port guards that throw on unknown reads,
385
+ * stays safe.
335
386
  */
336
387
  export function isProviderInstrumentation(
337
388
  value: unknown,
338
389
  ): value is ProviderInstrumentation {
339
390
  return (
340
391
  isObject(value) &&
392
+ "record" in value &&
393
+ "custom" in value &&
394
+ "isEnabled" in value &&
341
395
  typeof value.record === "function" &&
342
396
  typeof value.custom === "function" &&
343
397
  typeof value.isEnabled === "function"
@@ -346,11 +400,16 @@ export function isProviderInstrumentation(
346
400
 
347
401
  /**
348
402
  * Return whether a value is a provider instrumentation port.
403
+ *
404
+ * Checks key presence with `in` before reading so probing proxy-backed
405
+ * objects stays safe.
349
406
  */
350
407
  export function isProviderInstrumentationPort(
351
408
  value: unknown,
352
409
  ): value is ProviderInstrumentationPort {
353
- return isObject(value) && typeof value.record === "function";
410
+ return (
411
+ isObject(value) && "record" in value && typeof value.record === "function"
412
+ );
354
413
  }
355
414
 
356
415
  function resolveProviderInstrumentationValue(
@@ -376,8 +435,12 @@ export function resolveProviderInstrumentationPort(
376
435
  if (!isObject(target)) return undefined;
377
436
 
378
437
  return (
379
- resolveProviderInstrumentationValue(target.instrumentation) ??
380
- resolveProviderInstrumentationValue(target.devtools)
438
+ resolveProviderInstrumentationValue(
439
+ "instrumentation" in target ? target.instrumentation : undefined,
440
+ ) ??
441
+ resolveProviderInstrumentationValue(
442
+ "devtools" in target ? target.devtools : undefined,
443
+ )
381
444
  );
382
445
  }
383
446
 
@@ -393,6 +456,18 @@ function withProviderDetails(providerName: string, details: unknown): unknown {
393
456
  return { providerName, value: details };
394
457
  }
395
458
 
459
+ function withInstrumentationProviderDetails(
460
+ event: ProviderInstrumentationEventInput,
461
+ providerName: string,
462
+ ): ProviderInstrumentationEventInput {
463
+ if (event.type === "provider") return event;
464
+
465
+ return {
466
+ ...event,
467
+ details: withProviderDetails(providerName, event.details),
468
+ } as ProviderInstrumentationEventInput;
469
+ }
470
+
396
471
  /**
397
472
  * Create a provider instrumentation helper that handles watcher checks,
398
473
  * default watcher assignment, redaction, and sink failures.
@@ -423,12 +498,16 @@ export function createProviderInstrumentation(
423
498
  options.watcher && event.watcher === undefined
424
499
  ? { ...event, watcher: options.watcher }
425
500
  : event;
501
+ const eventWithProvider = withInstrumentationProviderDetails(
502
+ eventWithWatcher,
503
+ options.providerName,
504
+ );
426
505
 
427
506
  let redacted: ProviderInstrumentationEventInput;
428
507
  try {
429
508
  redacted = options.redact
430
- ? options.redact(redactValue(eventWithWatcher))
431
- : redactValue(eventWithWatcher);
509
+ ? options.redact(redactValue(eventWithProvider))
510
+ : redactValue(eventWithProvider);
432
511
  } catch {
433
512
  return undefined;
434
513
  }
@@ -0,0 +1,234 @@
1
+ /**
2
+ * Static provider package metadata declared in package.json under
3
+ * `beignet.provider`.
4
+ *
5
+ * This metadata is for docs and tooling. It must stay side-effect-free and
6
+ * does not change provider setup, ordering, or runtime port merging behavior.
7
+ */
8
+
9
+ export type ProviderPackagePortMetadata = {
10
+ name: string;
11
+ type: string;
12
+ };
13
+
14
+ export type ProviderPackageRegistrationSeverity = "warning" | "hint";
15
+
16
+ export type ProviderPackageRegistrationMetadata = {
17
+ required?: boolean;
18
+ severity?: ProviderPackageRegistrationSeverity;
19
+ tokens?: readonly string[];
20
+ };
21
+
22
+ export type ProviderPackageMetadata = {
23
+ displayName?: string;
24
+ ports?: readonly string[];
25
+ appPorts?: readonly ProviderPackagePortMetadata[];
26
+ env?: readonly string[];
27
+ requiredEnv?: readonly string[];
28
+ registration?: ProviderPackageRegistrationMetadata;
29
+ watchers?: readonly string[];
30
+ };
31
+
32
+ export type ProviderPackageMetadataIssue = {
33
+ path: string;
34
+ message: string;
35
+ };
36
+
37
+ export type ProviderPackageMetadataParseResult =
38
+ | { success: true; metadata: ProviderPackageMetadata }
39
+ | { success: false; issues: readonly ProviderPackageMetadataIssue[] };
40
+
41
+ export function parseProviderPackageMetadata(
42
+ input: unknown,
43
+ ): ProviderPackageMetadataParseResult {
44
+ if (!isRecord(input)) {
45
+ return {
46
+ success: false,
47
+ issues: [
48
+ {
49
+ path: "beignet.provider",
50
+ message: "must be an object",
51
+ },
52
+ ],
53
+ };
54
+ }
55
+
56
+ const issues: ProviderPackageMetadataIssue[] = [];
57
+ const metadata: ProviderPackageMetadata = {};
58
+
59
+ if (input.displayName !== undefined) {
60
+ if (typeof input.displayName !== "string") {
61
+ issues.push({
62
+ path: "beignet.provider.displayName",
63
+ message: "must be a string",
64
+ });
65
+ } else {
66
+ metadata.displayName = input.displayName;
67
+ }
68
+ }
69
+
70
+ const ports = parseStringArray(input.ports, "beignet.provider.ports", issues);
71
+ if (ports !== undefined) metadata.ports = ports;
72
+
73
+ const env = parseStringArray(input.env, "beignet.provider.env", issues);
74
+ if (env !== undefined) metadata.env = env;
75
+
76
+ const requiredEnv = parseStringArray(
77
+ input.requiredEnv,
78
+ "beignet.provider.requiredEnv",
79
+ issues,
80
+ );
81
+ if (requiredEnv !== undefined) {
82
+ metadata.requiredEnv = requiredEnv;
83
+ const envSet = new Set(env ?? []);
84
+ for (const envVar of requiredEnv) {
85
+ if (!envSet.has(envVar)) {
86
+ issues.push({
87
+ path: "beignet.provider.requiredEnv",
88
+ message: `${envVar} must also be listed in beignet.provider.env`,
89
+ });
90
+ }
91
+ }
92
+ }
93
+
94
+ const watchers = parseStringArray(
95
+ input.watchers,
96
+ "beignet.provider.watchers",
97
+ issues,
98
+ );
99
+ if (watchers !== undefined) metadata.watchers = watchers;
100
+
101
+ const appPorts = parseAppPorts(input.appPorts, issues);
102
+ if (appPorts !== undefined) metadata.appPorts = appPorts;
103
+
104
+ const registration = parseRegistration(input.registration, issues);
105
+ if (registration !== undefined) metadata.registration = registration;
106
+
107
+ if (issues.length > 0) {
108
+ return { success: false, issues };
109
+ }
110
+
111
+ return { success: true, metadata };
112
+ }
113
+
114
+ function parseStringArray(
115
+ value: unknown,
116
+ path: string,
117
+ issues: ProviderPackageMetadataIssue[],
118
+ ): string[] | undefined {
119
+ if (value === undefined) return undefined;
120
+ if (!Array.isArray(value)) {
121
+ issues.push({ path, message: "must be an array of strings" });
122
+ return undefined;
123
+ }
124
+
125
+ const parsed: string[] = [];
126
+ for (const [index, entry] of value.entries()) {
127
+ if (typeof entry !== "string") {
128
+ issues.push({
129
+ path: `${path}[${index}]`,
130
+ message: "must be a string",
131
+ });
132
+ continue;
133
+ }
134
+ parsed.push(entry);
135
+ }
136
+
137
+ return parsed;
138
+ }
139
+
140
+ function parseAppPorts(
141
+ value: unknown,
142
+ issues: ProviderPackageMetadataIssue[],
143
+ ): ProviderPackagePortMetadata[] | undefined {
144
+ if (value === undefined) return undefined;
145
+ const path = "beignet.provider.appPorts";
146
+ if (!Array.isArray(value)) {
147
+ issues.push({ path, message: "must be an array of port metadata objects" });
148
+ return undefined;
149
+ }
150
+
151
+ const parsed: ProviderPackagePortMetadata[] = [];
152
+ for (const [index, entry] of value.entries()) {
153
+ const entryPath = `${path}[${index}]`;
154
+ if (!isRecord(entry)) {
155
+ issues.push({ path: entryPath, message: "must be an object" });
156
+ continue;
157
+ }
158
+ if (typeof entry.name !== "string") {
159
+ issues.push({ path: `${entryPath}.name`, message: "must be a string" });
160
+ }
161
+ if (typeof entry.type !== "string") {
162
+ issues.push({ path: `${entryPath}.type`, message: "must be a string" });
163
+ }
164
+ if (typeof entry.name === "string" && typeof entry.type === "string") {
165
+ parsed.push({ name: entry.name, type: entry.type });
166
+ }
167
+ }
168
+
169
+ return parsed;
170
+ }
171
+
172
+ function parseRegistration(
173
+ value: unknown,
174
+ issues: ProviderPackageMetadataIssue[],
175
+ ): ProviderPackageRegistrationMetadata | undefined {
176
+ if (value === undefined) return undefined;
177
+ const path = "beignet.provider.registration";
178
+ if (!isRecord(value)) {
179
+ issues.push({ path, message: "must be an object" });
180
+ return undefined;
181
+ }
182
+
183
+ const registration: ProviderPackageRegistrationMetadata = {};
184
+ if (value.required !== undefined) {
185
+ if (typeof value.required !== "boolean") {
186
+ issues.push({ path: `${path}.required`, message: "must be a boolean" });
187
+ } else {
188
+ registration.required = value.required;
189
+ }
190
+ }
191
+
192
+ if (value.severity !== undefined) {
193
+ if (value.severity !== "warning" && value.severity !== "hint") {
194
+ issues.push({
195
+ path: `${path}.severity`,
196
+ message: 'must be "warning" or "hint"',
197
+ });
198
+ } else {
199
+ registration.severity = value.severity;
200
+ }
201
+ }
202
+
203
+ if (registration.required === true && registration.severity === "hint") {
204
+ issues.push({
205
+ path: `${path}.severity`,
206
+ message: 'must not be "hint" when registration is required',
207
+ });
208
+ }
209
+
210
+ const tokens = parseStringArray(value.tokens, `${path}.tokens`, issues);
211
+ if (tokens !== undefined) registration.tokens = tokens;
212
+
213
+ if ((tokens?.length ?? 0) === 0) {
214
+ if (registration.required === true) {
215
+ issues.push({
216
+ path: `${path}.tokens`,
217
+ message:
218
+ "must include at least one token when registration is required",
219
+ });
220
+ } else if (registration.severity !== undefined) {
221
+ issues.push({
222
+ path: `${path}.tokens`,
223
+ message:
224
+ "must include at least one token when registration severity is set",
225
+ });
226
+ }
227
+ }
228
+
229
+ return registration;
230
+ }
231
+
232
+ function isRecord(value: unknown): value is Record<string, unknown> {
233
+ return typeof value === "object" && value !== null && !Array.isArray(value);
234
+ }