@porulle/core 0.64.0 → 0.65.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. package/dist/adapters/email-render.d.ts +18 -0
  2. package/dist/adapters/email-render.d.ts.map +1 -0
  3. package/dist/adapters/email-render.js +37 -0
  4. package/dist/auth/actor.d.ts.map +1 -1
  5. package/dist/auth/actor.js +11 -0
  6. package/dist/auth/auth-failure.d.ts +0 -2
  7. package/dist/auth/auth-failure.d.ts.map +1 -1
  8. package/dist/auth/auth-failure.js +0 -4
  9. package/dist/auth/middleware.d.ts +0 -1
  10. package/dist/auth/middleware.d.ts.map +1 -1
  11. package/dist/auth/middleware.js +7 -6
  12. package/dist/auth/permissions.d.ts +2 -0
  13. package/dist/auth/permissions.d.ts.map +1 -1
  14. package/dist/auth/permissions.js +8 -6
  15. package/dist/auth/role-authority.d.ts +0 -1
  16. package/dist/auth/role-authority.d.ts.map +1 -1
  17. package/dist/auth/role-authority.js +1 -8
  18. package/dist/auth/setup.d.ts.map +1 -1
  19. package/dist/auth/setup.js +5 -0
  20. package/dist/auth/strict-org-resolution.d.ts +8 -1
  21. package/dist/auth/strict-org-resolution.d.ts.map +1 -1
  22. package/dist/auth/strict-org-resolution.js +9 -19
  23. package/dist/auth/system-actor.d.ts +3 -2
  24. package/dist/auth/system-actor.d.ts.map +1 -1
  25. package/dist/auth/system-actor.js +3 -3
  26. package/dist/config/defaults.d.ts.map +1 -1
  27. package/dist/config/defaults.js +3 -20
  28. package/dist/config/define-config.d.ts +2 -2
  29. package/dist/config/define-config.d.ts.map +1 -1
  30. package/dist/config/define-config.js +3 -2
  31. package/dist/config/types.d.ts +2 -3
  32. package/dist/config/types.d.ts.map +1 -1
  33. package/dist/hooks/checkout.d.ts +2 -15
  34. package/dist/hooks/checkout.d.ts.map +1 -1
  35. package/dist/hooks/checkout.js +2 -51
  36. package/dist/index.d.ts +11 -19
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +11 -12
  39. package/dist/interfaces/rest/router.js +3 -3
  40. package/dist/interfaces/rest/routes/admin/compensation-failures.d.ts.map +1 -1
  41. package/dist/interfaces/rest/routes/admin/compensation-failures.js +5 -5
  42. package/dist/interfaces/rest/routes/admin/entity-field-definitions.js +5 -5
  43. package/dist/interfaces/rest/routes/admin/staff.d.ts.map +1 -1
  44. package/dist/interfaces/rest/routes/admin/staff.js +2 -3
  45. package/dist/interfaces/rest/routes/analytics.d.ts.map +1 -1
  46. package/dist/interfaces/rest/routes/analytics.js +2 -2
  47. package/dist/interfaces/rest/routes/carts.d.ts.map +1 -1
  48. package/dist/interfaces/rest/routes/carts.js +12 -12
  49. package/dist/interfaces/rest/routes/catalog.js +37 -37
  50. package/dist/interfaces/rest/routes/checkout.d.ts.map +1 -1
  51. package/dist/interfaces/rest/routes/checkout.js +9 -10
  52. package/dist/interfaces/rest/routes/customers.d.ts.map +1 -1
  53. package/dist/interfaces/rest/routes/customers.js +12 -12
  54. package/dist/interfaces/rest/routes/documents.d.ts.map +1 -1
  55. package/dist/interfaces/rest/routes/documents.js +9 -9
  56. package/dist/interfaces/rest/routes/inventory.d.ts.map +1 -1
  57. package/dist/interfaces/rest/routes/inventory.js +8 -8
  58. package/dist/interfaces/rest/routes/media.d.ts.map +1 -1
  59. package/dist/interfaces/rest/routes/media.js +5 -5
  60. package/dist/interfaces/rest/routes/orders.d.ts.map +1 -1
  61. package/dist/interfaces/rest/routes/orders.js +32 -32
  62. package/dist/interfaces/rest/routes/payments.d.ts.map +1 -1
  63. package/dist/interfaces/rest/routes/payments.js +2 -2
  64. package/dist/interfaces/rest/routes/pricing.d.ts.map +1 -1
  65. package/dist/interfaces/rest/routes/pricing.js +8 -8
  66. package/dist/interfaces/rest/routes/promotions.d.ts.map +1 -1
  67. package/dist/interfaces/rest/routes/promotions.js +7 -7
  68. package/dist/interfaces/rest/routes/search.d.ts.map +1 -1
  69. package/dist/interfaces/rest/routes/search.js +3 -3
  70. package/dist/interfaces/rest/routes/settings.d.ts.map +1 -1
  71. package/dist/interfaces/rest/routes/settings.js +4 -4
  72. package/dist/interfaces/rest/routes/shipping.d.ts.map +1 -1
  73. package/dist/interfaces/rest/routes/shipping.js +9 -9
  74. package/dist/interfaces/rest/routes/tax.d.ts.map +1 -1
  75. package/dist/interfaces/rest/routes/tax.js +9 -9
  76. package/dist/interfaces/rest/routes/webhooks.d.ts.map +1 -1
  77. package/dist/interfaces/rest/routes/webhooks.js +4 -4
  78. package/dist/interfaces/rest/utils.d.ts +1 -1
  79. package/dist/interfaces/rest/utils.d.ts.map +1 -1
  80. package/dist/interfaces/rest/utils.js +4 -13
  81. package/dist/jobs.d.ts +1 -0
  82. package/dist/jobs.d.ts.map +1 -1
  83. package/dist/jobs.js +1 -0
  84. package/dist/kernel/database/adapter.d.ts +9 -0
  85. package/dist/kernel/database/adapter.d.ts.map +1 -1
  86. package/dist/kernel/database/adapter.js +1 -1
  87. package/dist/kernel/database/migrate.d.ts +0 -4
  88. package/dist/kernel/database/migrate.d.ts.map +1 -1
  89. package/dist/kernel/database/migrate.js +2 -14
  90. package/dist/kernel/database/pglite-transaction.d.ts +28 -0
  91. package/dist/kernel/database/pglite-transaction.d.ts.map +1 -0
  92. package/dist/kernel/database/pglite-transaction.js +52 -0
  93. package/dist/kernel/database/tx-context.d.ts +0 -1
  94. package/dist/kernel/database/tx-context.d.ts.map +1 -1
  95. package/dist/kernel/database/tx-context.js +2 -14
  96. package/dist/kernel/database/unique-violation.d.ts +3 -0
  97. package/dist/kernel/database/unique-violation.d.ts.map +1 -0
  98. package/dist/kernel/database/unique-violation.js +9 -0
  99. package/dist/kernel/error-mapper.d.ts.map +1 -1
  100. package/dist/kernel/error-mapper.js +1 -0
  101. package/dist/kernel/errors.d.ts +12 -0
  102. package/dist/kernel/errors.d.ts.map +1 -1
  103. package/dist/kernel/errors.js +16 -0
  104. package/dist/kernel/hooks/create-context.d.ts +18 -9
  105. package/dist/kernel/hooks/create-context.d.ts.map +1 -1
  106. package/dist/kernel/hooks/create-context.js +24 -3
  107. package/dist/kernel/hooks/registry.d.ts +0 -19
  108. package/dist/kernel/hooks/registry.d.ts.map +1 -1
  109. package/dist/kernel/hooks/registry.js +0 -32
  110. package/dist/kernel/jobs/drizzle-adapter.d.ts.map +1 -1
  111. package/dist/kernel/jobs/drizzle-adapter.js +3 -10
  112. package/dist/kernel/jobs/prepare-enqueue.d.ts +20 -0
  113. package/dist/kernel/jobs/prepare-enqueue.d.ts.map +1 -0
  114. package/dist/kernel/jobs/prepare-enqueue.js +24 -0
  115. package/dist/kernel/jobs/types.d.ts +0 -4
  116. package/dist/kernel/jobs/types.d.ts.map +1 -1
  117. package/dist/kernel/jobs/types.js +0 -4
  118. package/dist/kernel/local-api.d.ts +0 -33
  119. package/dist/kernel/local-api.d.ts.map +1 -1
  120. package/dist/kernel/local-api.js +0 -36
  121. package/dist/kernel/plugin/manifest.d.ts +3 -5
  122. package/dist/kernel/plugin/manifest.d.ts.map +1 -1
  123. package/dist/modules/analytics/service.d.ts +0 -6
  124. package/dist/modules/analytics/service.d.ts.map +1 -1
  125. package/dist/modules/analytics/service.js +0 -32
  126. package/dist/modules/cart/service.d.ts.map +1 -1
  127. package/dist/modules/cart/service.js +5 -17
  128. package/dist/modules/catalog/entity-service.d.ts.map +1 -1
  129. package/dist/modules/catalog/entity-service.js +9 -17
  130. package/dist/modules/catalog/import-service.d.ts.map +1 -1
  131. package/dist/modules/catalog/import-service.js +4 -13
  132. package/dist/modules/catalog/service.d.ts +1 -81
  133. package/dist/modules/catalog/service.d.ts.map +1 -1
  134. package/dist/modules/catalog/service.js +1 -8
  135. package/dist/modules/customers/service.d.ts.map +1 -1
  136. package/dist/modules/customers/service.js +5 -17
  137. package/dist/modules/documents/render.d.ts +0 -3
  138. package/dist/modules/documents/render.d.ts.map +1 -1
  139. package/dist/modules/documents/render.js +2 -17
  140. package/dist/modules/fulfillment/service.d.ts.map +1 -1
  141. package/dist/modules/fulfillment/service.js +8 -26
  142. package/dist/modules/inventory/service.d.ts.map +1 -1
  143. package/dist/modules/inventory/service.js +3 -20
  144. package/dist/modules/media/service.d.ts.map +1 -1
  145. package/dist/modules/media/service.js +2 -10
  146. package/dist/modules/orders/quote.d.ts.map +1 -1
  147. package/dist/modules/orders/quote.js +1 -2
  148. package/dist/modules/orders/service.d.ts.map +1 -1
  149. package/dist/modules/orders/service.js +4 -17
  150. package/dist/modules/pricing/service.d.ts.map +1 -1
  151. package/dist/modules/pricing/service.js +7 -18
  152. package/dist/modules/promotions/service.d.ts.map +1 -1
  153. package/dist/modules/promotions/service.js +4 -16
  154. package/dist/modules/tax/service.d.ts +1 -3
  155. package/dist/modules/tax/service.d.ts.map +1 -1
  156. package/dist/modules/tax/service.js +16 -52
  157. package/dist/modules/webhooks/hook.d.ts.map +1 -1
  158. package/dist/modules/webhooks/hook.js +3 -2
  159. package/dist/modules/webhooks/service.d.ts.map +1 -1
  160. package/dist/modules/webhooks/service.js +1 -50
  161. package/dist/runtime/commerce.d.ts.map +1 -1
  162. package/dist/runtime/commerce.js +4 -11
  163. package/dist/runtime/kernel-modules.d.ts +38 -1799
  164. package/dist/runtime/kernel-modules.d.ts.map +1 -1
  165. package/dist/runtime/kernel-modules.js +160 -66
  166. package/dist/runtime/kernel-types.d.ts +3 -15
  167. package/dist/runtime/kernel-types.d.ts.map +1 -1
  168. package/dist/runtime/kernel-types.js +0 -10
  169. package/dist/runtime/kernel.d.ts +2 -3
  170. package/dist/runtime/kernel.d.ts.map +1 -1
  171. package/dist/runtime/kernel.js +10 -51
  172. package/dist/runtime/server.d.ts +1 -1
  173. package/dist/runtime/server.d.ts.map +1 -1
  174. package/dist/test-utils/create-pglite-adapter.d.ts.map +1 -1
  175. package/dist/test-utils/create-pglite-adapter.js +5 -62
  176. package/dist/test-utils/create-plugin-test-app.d.ts.map +1 -1
  177. package/dist/test-utils/create-plugin-test-app.js +13 -32
  178. package/dist/test-utils/rest-api-test-utils.d.ts +0 -12
  179. package/dist/test-utils/rest-api-test-utils.d.ts.map +1 -1
  180. package/dist/test-utils/rest-api-test-utils.js +3 -70
  181. package/dist/test-utils/test-actors.d.ts +9 -0
  182. package/dist/test-utils/test-actors.d.ts.map +1 -1
  183. package/dist/test-utils/test-actors.js +62 -0
  184. package/dist/testing.d.ts +1 -4
  185. package/dist/testing.d.ts.map +1 -1
  186. package/dist/testing.js +1 -4
  187. package/dist/utils/escape-html.d.ts +3 -0
  188. package/dist/utils/escape-html.d.ts.map +1 -0
  189. package/dist/utils/escape-html.js +9 -0
  190. package/dist/utils/id.d.ts +0 -1
  191. package/dist/utils/id.d.ts.map +1 -1
  192. package/dist/utils/id.js +0 -3
  193. package/dist/utils/logger.d.ts +1 -1
  194. package/dist/utils/logger.d.ts.map +1 -1
  195. package/dist/utils/logger.js +1 -1
  196. package/dist/utils/money.d.ts +13 -0
  197. package/dist/utils/money.d.ts.map +1 -0
  198. package/dist/utils/money.js +58 -0
  199. package/package.json +5 -6
  200. package/src/adapters/email-render.ts +63 -0
  201. package/src/auth/actor.ts +14 -0
  202. package/src/auth/auth-failure.ts +0 -5
  203. package/src/auth/middleware.ts +7 -6
  204. package/src/auth/permissions.ts +12 -6
  205. package/src/auth/role-authority.ts +1 -10
  206. package/src/auth/setup.ts +8 -0
  207. package/src/auth/strict-org-resolution.ts +9 -16
  208. package/src/auth/system-actor.ts +3 -3
  209. package/src/config/defaults.ts +3 -20
  210. package/src/config/define-config.ts +5 -4
  211. package/src/config/types.ts +2 -2
  212. package/src/hooks/checkout.ts +2 -86
  213. package/src/index.ts +9 -36
  214. package/src/interfaces/rest/router.ts +3 -3
  215. package/src/interfaces/rest/routes/admin/compensation-failures.ts +5 -5
  216. package/src/interfaces/rest/routes/admin/entity-field-definitions.ts +5 -5
  217. package/src/interfaces/rest/routes/admin/staff.ts +2 -3
  218. package/src/interfaces/rest/routes/analytics.ts +2 -2
  219. package/src/interfaces/rest/routes/carts.ts +12 -12
  220. package/src/interfaces/rest/routes/catalog.ts +37 -37
  221. package/src/interfaces/rest/routes/checkout.ts +8 -10
  222. package/src/interfaces/rest/routes/customers.ts +12 -12
  223. package/src/interfaces/rest/routes/documents.ts +9 -9
  224. package/src/interfaces/rest/routes/inventory.ts +8 -8
  225. package/src/interfaces/rest/routes/media.ts +5 -5
  226. package/src/interfaces/rest/routes/orders.ts +32 -32
  227. package/src/interfaces/rest/routes/payments.ts +2 -2
  228. package/src/interfaces/rest/routes/pricing.ts +8 -8
  229. package/src/interfaces/rest/routes/promotions.ts +7 -7
  230. package/src/interfaces/rest/routes/search.ts +3 -3
  231. package/src/interfaces/rest/routes/settings.ts +4 -4
  232. package/src/interfaces/rest/routes/shipping.ts +9 -9
  233. package/src/interfaces/rest/routes/tax.ts +9 -9
  234. package/src/interfaces/rest/routes/webhooks.ts +4 -4
  235. package/src/interfaces/rest/utils.ts +4 -14
  236. package/src/jobs.ts +2 -1
  237. package/src/kernel/database/adapter.ts +1 -1
  238. package/src/kernel/database/migrate.ts +2 -17
  239. package/src/kernel/database/pglite-transaction.ts +61 -0
  240. package/src/kernel/database/tx-context.ts +2 -20
  241. package/src/kernel/database/unique-violation.ts +7 -0
  242. package/src/kernel/error-mapper.ts +1 -0
  243. package/src/kernel/errors.ts +18 -0
  244. package/src/kernel/hooks/create-context.ts +38 -8
  245. package/src/kernel/hooks/registry.ts +0 -37
  246. package/src/kernel/jobs/drizzle-adapter.ts +4 -15
  247. package/src/kernel/jobs/prepare-enqueue.ts +42 -0
  248. package/src/kernel/jobs/types.ts +0 -5
  249. package/src/kernel/local-api.ts +0 -44
  250. package/src/kernel/plugin/manifest.ts +3 -5
  251. package/src/modules/analytics/service.ts +0 -36
  252. package/src/modules/cart/service.ts +6 -29
  253. package/src/modules/catalog/entity-service.ts +9 -19
  254. package/src/modules/catalog/import-service.ts +4 -11
  255. package/src/modules/catalog/service.ts +2 -286
  256. package/src/modules/customers/service.ts +6 -27
  257. package/src/modules/documents/render.ts +2 -19
  258. package/src/modules/fulfillment/service.ts +8 -27
  259. package/src/modules/inventory/service.ts +3 -21
  260. package/src/modules/media/service.ts +2 -8
  261. package/src/modules/orders/quote.ts +1 -2
  262. package/src/modules/orders/service.ts +5 -30
  263. package/src/modules/pricing/service.ts +12 -30
  264. package/src/modules/promotions/service.ts +5 -28
  265. package/src/modules/tax/service.ts +20 -48
  266. package/src/modules/webhooks/hook.ts +3 -2
  267. package/src/modules/webhooks/service.ts +1 -42
  268. package/src/runtime/commerce.ts +4 -11
  269. package/src/runtime/kernel-modules.ts +191 -67
  270. package/src/runtime/kernel-types.ts +3 -26
  271. package/src/runtime/kernel.ts +11 -66
  272. package/src/runtime/server.ts +1 -3
  273. package/src/test-utils/create-pglite-adapter.ts +5 -67
  274. package/src/test-utils/create-plugin-test-app.ts +13 -52
  275. package/src/test-utils/rest-api-test-utils.ts +3 -70
  276. package/src/test-utils/test-actors.ts +66 -0
  277. package/src/testing.ts +1 -3
  278. package/src/utils/escape-html.ts +9 -0
  279. package/src/utils/id.ts +0 -4
  280. package/src/utils/logger.ts +1 -1
  281. package/src/utils/money.ts +62 -0
  282. package/dist/auth/access.d.ts +0 -101
  283. package/dist/auth/access.d.ts.map +0 -1
  284. package/dist/auth/access.js +0 -128
  285. package/dist/generated/plugin-manifest.d.ts +0 -51
  286. package/dist/generated/plugin-manifest.d.ts.map +0 -1
  287. package/dist/generated/plugin-manifest.js +0 -21
  288. package/dist/kernel/factory/repository-factory.d.ts +0 -71
  289. package/dist/kernel/factory/repository-factory.d.ts.map +0 -1
  290. package/dist/kernel/factory/repository-factory.js +0 -138
  291. package/dist/kernel/http-error.d.ts +0 -30
  292. package/dist/kernel/http-error.d.ts.map +0 -1
  293. package/dist/kernel/http-error.js +0 -35
  294. package/dist/kernel/jobs/builtin-job-tasks.d.ts +0 -3
  295. package/dist/kernel/jobs/builtin-job-tasks.d.ts.map +0 -1
  296. package/dist/kernel/jobs/builtin-job-tasks.js +0 -6
  297. package/dist/kernel/module/define.d.ts +0 -21
  298. package/dist/kernel/module/define.d.ts.map +0 -1
  299. package/dist/kernel/module/define.js +0 -3
  300. package/dist/kernel/module/index.d.ts +0 -4
  301. package/dist/kernel/module/index.d.ts.map +0 -1
  302. package/dist/kernel/module/index.js +0 -2
  303. package/dist/kernel/module/topo-sort.d.ts +0 -7
  304. package/dist/kernel/module/topo-sort.d.ts.map +0 -1
  305. package/dist/kernel/module/topo-sort.js +0 -89
  306. package/dist/kernel/query/executor.d.ts +0 -21
  307. package/dist/kernel/query/executor.d.ts.map +0 -1
  308. package/dist/kernel/query/executor.js +0 -128
  309. package/dist/kernel/query/registry.d.ts +0 -33
  310. package/dist/kernel/query/registry.d.ts.map +0 -1
  311. package/dist/kernel/query/registry.js +0 -20
  312. package/dist/kernel/service-registry.d.ts +0 -109
  313. package/dist/kernel/service-registry.d.ts.map +0 -1
  314. package/dist/kernel/service-registry.js +0 -26
  315. package/dist/modules/analytics/hooks.d.ts +0 -13
  316. package/dist/modules/analytics/hooks.d.ts.map +0 -1
  317. package/dist/modules/analytics/hooks.js +0 -12
  318. package/dist/modules/analytics/module.d.ts +0 -3
  319. package/dist/modules/analytics/module.d.ts.map +0 -1
  320. package/dist/modules/analytics/module.js +0 -24
  321. package/dist/modules/analytics/repository/index.d.ts +0 -5
  322. package/dist/modules/analytics/repository/index.d.ts.map +0 -1
  323. package/dist/modules/analytics/repository/index.js +0 -1
  324. package/dist/modules/audit/index.d.ts +0 -2
  325. package/dist/modules/audit/index.d.ts.map +0 -1
  326. package/dist/modules/audit/index.js +0 -1
  327. package/dist/modules/audit/module.d.ts +0 -180
  328. package/dist/modules/audit/module.d.ts.map +0 -1
  329. package/dist/modules/audit/module.js +0 -8
  330. package/dist/modules/cart/access.d.ts +0 -11
  331. package/dist/modules/cart/access.d.ts.map +0 -1
  332. package/dist/modules/cart/access.js +0 -18
  333. package/dist/modules/cart/module.d.ts +0 -14
  334. package/dist/modules/cart/module.d.ts.map +0 -1
  335. package/dist/modules/cart/module.js +0 -17
  336. package/dist/modules/catalog/module.d.ts +0 -26
  337. package/dist/modules/catalog/module.d.ts.map +0 -1
  338. package/dist/modules/catalog/module.js +0 -33
  339. package/dist/modules/customers/index.d.ts +0 -2
  340. package/dist/modules/customers/index.d.ts.map +0 -1
  341. package/dist/modules/customers/index.js +0 -1
  342. package/dist/modules/customers/module.d.ts +0 -563
  343. package/dist/modules/customers/module.d.ts.map +0 -1
  344. package/dist/modules/customers/module.js +0 -20
  345. package/dist/modules/documents/module.d.ts +0 -7
  346. package/dist/modules/documents/module.d.ts.map +0 -1
  347. package/dist/modules/documents/module.js +0 -13
  348. package/dist/modules/fulfillment/module.d.ts +0 -13
  349. package/dist/modules/fulfillment/module.d.ts.map +0 -1
  350. package/dist/modules/fulfillment/module.js +0 -23
  351. package/dist/modules/inventory/module.d.ts +0 -13
  352. package/dist/modules/inventory/module.d.ts.map +0 -1
  353. package/dist/modules/inventory/module.js +0 -20
  354. package/dist/modules/media/index.d.ts +0 -2
  355. package/dist/modules/media/index.d.ts.map +0 -1
  356. package/dist/modules/media/index.js +0 -1
  357. package/dist/modules/media/module.d.ts +0 -360
  358. package/dist/modules/media/module.d.ts.map +0 -1
  359. package/dist/modules/media/module.js +0 -24
  360. package/dist/modules/orders/module.d.ts +0 -25
  361. package/dist/modules/orders/module.d.ts.map +0 -1
  362. package/dist/modules/orders/module.js +0 -33
  363. package/dist/modules/organization/index.d.ts +0 -2
  364. package/dist/modules/organization/index.d.ts.map +0 -1
  365. package/dist/modules/organization/index.js +0 -1
  366. package/dist/modules/organization/module.d.ts +0 -205
  367. package/dist/modules/organization/module.d.ts.map +0 -1
  368. package/dist/modules/organization/module.js +0 -8
  369. package/dist/modules/payments/module.d.ts +0 -3
  370. package/dist/modules/payments/module.d.ts.map +0 -1
  371. package/dist/modules/payments/module.js +0 -7
  372. package/dist/modules/payments/repository/index.d.ts +0 -5
  373. package/dist/modules/payments/repository/index.d.ts.map +0 -1
  374. package/dist/modules/payments/repository/index.js +0 -1
  375. package/dist/modules/pricing/index.d.ts +0 -2
  376. package/dist/modules/pricing/index.d.ts.map +0 -1
  377. package/dist/modules/pricing/index.js +0 -1
  378. package/dist/modules/pricing/module.d.ts +0 -14
  379. package/dist/modules/pricing/module.d.ts.map +0 -1
  380. package/dist/modules/pricing/module.js +0 -17
  381. package/dist/modules/promotions/module.d.ts +0 -14
  382. package/dist/modules/promotions/module.d.ts.map +0 -1
  383. package/dist/modules/promotions/module.js +0 -19
  384. package/dist/modules/search/module.d.ts +0 -8
  385. package/dist/modules/search/module.d.ts.map +0 -1
  386. package/dist/modules/search/module.js +0 -22
  387. package/dist/modules/search/repository/index.d.ts +0 -5
  388. package/dist/modules/search/repository/index.d.ts.map +0 -1
  389. package/dist/modules/search/repository/index.js +0 -1
  390. package/dist/modules/settings/module.d.ts +0 -6
  391. package/dist/modules/settings/module.d.ts.map +0 -1
  392. package/dist/modules/settings/module.js +0 -12
  393. package/dist/modules/shipping/module.d.ts +0 -12
  394. package/dist/modules/shipping/module.d.ts.map +0 -1
  395. package/dist/modules/shipping/module.js +0 -14
  396. package/dist/modules/tax/module.d.ts +0 -7
  397. package/dist/modules/tax/module.d.ts.map +0 -1
  398. package/dist/modules/tax/module.js +0 -13
  399. package/dist/modules/webhooks/index.d.ts +0 -2
  400. package/dist/modules/webhooks/index.d.ts.map +0 -1
  401. package/dist/modules/webhooks/index.js +0 -1
  402. package/dist/modules/webhooks/module.d.ts +0 -403
  403. package/dist/modules/webhooks/module.d.ts.map +0 -1
  404. package/dist/modules/webhooks/module.js +0 -16
  405. package/dist/test-utils/create-repository-test-harness.d.ts +0 -8
  406. package/dist/test-utils/create-repository-test-harness.d.ts.map +0 -1
  407. package/dist/test-utils/create-repository-test-harness.js +0 -7
  408. package/dist/test-utils/create-test-plugin-context.d.ts +0 -38
  409. package/dist/test-utils/create-test-plugin-context.d.ts.map +0 -1
  410. package/dist/test-utils/create-test-plugin-context.js +0 -39
  411. package/dist/test-utils/typed-hooks.d.ts +0 -44
  412. package/dist/test-utils/typed-hooks.d.ts.map +0 -1
  413. package/dist/test-utils/typed-hooks.js +0 -36
  414. package/dist/types/commerce-types.d.ts +0 -34
  415. package/dist/types/commerce-types.d.ts.map +0 -1
  416. package/dist/types/commerce-types.js +0 -1
  417. package/src/auth/access.ts +0 -187
  418. package/src/generated/plugin-capabilities.d.ts +0 -21
  419. package/src/generated/plugin-manifest.ts +0 -24
  420. package/src/generated/plugin-repositories.d.ts +0 -21
  421. package/src/kernel/factory/repository-factory.ts +0 -244
  422. package/src/kernel/http-error.ts +0 -44
  423. package/src/kernel/jobs/builtin-job-tasks.ts +0 -17
  424. package/src/kernel/module/define.ts +0 -36
  425. package/src/kernel/module/index.ts +0 -3
  426. package/src/kernel/module/topo-sort.ts +0 -99
  427. package/src/kernel/query/executor.ts +0 -184
  428. package/src/kernel/query/registry.ts +0 -46
  429. package/src/kernel/service-registry.ts +0 -76
  430. package/src/modules/analytics/hooks.ts +0 -11
  431. package/src/modules/analytics/module.ts +0 -35
  432. package/src/modules/analytics/repository/index.ts +0 -5
  433. package/src/modules/audit/index.ts +0 -1
  434. package/src/modules/audit/module.ts +0 -11
  435. package/src/modules/cart/access.ts +0 -27
  436. package/src/modules/cart/module.ts +0 -32
  437. package/src/modules/catalog/module.ts +0 -80
  438. package/src/modules/customers/index.ts +0 -1
  439. package/src/modules/customers/module.ts +0 -29
  440. package/src/modules/documents/module.ts +0 -21
  441. package/src/modules/fulfillment/module.ts +0 -44
  442. package/src/modules/inventory/module.ts +0 -37
  443. package/src/modules/media/index.ts +0 -1
  444. package/src/modules/media/module.ts +0 -27
  445. package/src/modules/orders/module.ts +0 -67
  446. package/src/modules/organization/index.ts +0 -1
  447. package/src/modules/organization/module.ts +0 -11
  448. package/src/modules/payments/module.ts +0 -14
  449. package/src/modules/payments/repository/index.ts +0 -5
  450. package/src/modules/pricing/index.ts +0 -1
  451. package/src/modules/pricing/module.ts +0 -32
  452. package/src/modules/promotions/module.ts +0 -34
  453. package/src/modules/search/module.ts +0 -32
  454. package/src/modules/search/repository/index.ts +0 -5
  455. package/src/modules/settings/module.ts +0 -20
  456. package/src/modules/shipping/module.ts +0 -27
  457. package/src/modules/tax/module.ts +0 -21
  458. package/src/modules/webhooks/index.ts +0 -1
  459. package/src/modules/webhooks/module.ts +0 -24
  460. package/src/test-utils/create-repository-test-harness.ts +0 -16
  461. package/src/test-utils/create-test-plugin-context.ts +0 -66
  462. package/src/test-utils/typed-hooks.ts +0 -55
  463. package/src/types/commerce-types.ts +0 -34
@@ -28,18 +28,6 @@ export declare function createTestServer(overrides?: Partial<CommerceConfig>): P
28
28
  * Helper to parse JSON response from Hono Response
29
29
  */
30
30
  export declare function parseJsonResponse<T = unknown>(response: Response): Promise<T>;
31
- /**
32
- * Common test actor with staff permissions
33
- */
34
- export declare const testActor: Actor;
35
- /**
36
- * Test actor with read-only permissions
37
- */
38
- export declare const readonlyActor: Actor;
39
- /**
40
- * Test actor with no permissions
41
- */
42
- export declare const noPermActor: Actor;
43
31
  /**
44
32
  * Helper to create a mock request with actor context
45
33
  */
@@ -1 +1 @@
1
- {"version":3,"file":"rest-api-test-utils.d.ts","sourceRoot":"","sources":["../../src/test-utils/rest-api-test-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAOpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,KAAK,SAAS,GAAG;IACf,SAAS,EAAE;QACT,IAAI,EAAE,YAAY,CAAC;QACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;KACrB,CAAC;CACH,CAAC;AAiDF;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GACtC,OAAO,CAAC;IACT,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IACxB,MAAM,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;IACxC,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC,CAqDD;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,CAEnF;AAED;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,KAsCvB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,KAS3B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,KASzB,CAAC;AAEF;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE;IAClE,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,KAAK,CAAC;CACf,WAwBA;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,EACvB,OAAO,EAAE;IACP,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,KAAK,CAAC;CACf,qBAYF"}
1
+ {"version":3,"file":"rest-api-test-utils.d.ts","sourceRoot":"","sources":["../../src/test-utils/rest-api-test-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAOpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGrD,KAAK,SAAS,GAAG;IACf,SAAS,EAAE;QACT,IAAI,EAAE,YAAY,CAAC;QACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;KACrB,CAAC;CACH,CAAC;AAiDF;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GACtC,OAAO,CAAC;IACT,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IACxB,MAAM,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;IACxC,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC,CAqDD;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,CAEnF;AAKD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE;IAClE,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,KAAK,CAAC;CACf,WAwBA;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,EACvB,OAAO,EAAE;IACP,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,KAAK,CAAC;CACf,qBAYF"}
@@ -12,6 +12,7 @@ import { createRestRoutes } from "../interfaces/rest/index.js";
12
12
  import { createPGliteTestConfig } from "./create-test-config.js";
13
13
  import { CommerceValidationError } from "../kernel/errors.js";
14
14
  import { Ok, Err } from "../kernel/result.js";
15
+ import { testActor } from "./test-actors.js";
15
16
  const mockPaymentAdapter = {
16
17
  providerId: "test-payments",
17
18
  async createPaymentIntent(params) {
@@ -96,8 +97,8 @@ export async function createTestServer(overrides = {}) {
96
97
  }
97
98
  catch (error) {
98
99
  // Import error handling utilities
99
- const { mapErrorToResponse, mapErrorToStatus } = await import("../interfaces/rest/utils.js");
100
- return c.json(mapErrorToResponse(error), mapErrorToStatus(error));
100
+ const { errorBody, mapErrorToStatus } = await import("../interfaces/rest/utils.js");
101
+ return c.json(errorBody(error), mapErrorToStatus(error));
101
102
  }
102
103
  });
103
104
  // Add REST routes
@@ -110,74 +111,6 @@ export async function createTestServer(overrides = {}) {
110
111
  export async function parseJsonResponse(response) {
111
112
  return response.json();
112
113
  }
113
- /**
114
- * Common test actor with staff permissions
115
- */
116
- export const testActor = {
117
- type: "user",
118
- userId: "00000000-0000-0000-0000-000000000001",
119
- email: "test@example.com",
120
- name: "Test Staff",
121
- vendorId: null,
122
- organizationId: "org_default",
123
- role: "staff",
124
- permissions: [
125
- "catalog:create",
126
- "catalog:update",
127
- "catalog:read",
128
- "catalog:read:unpublished",
129
- "inventory:adjust",
130
- "inventory:read",
131
- "orders:create",
132
- "orders:create:on-behalf",
133
- "orders:read",
134
- "orders:update",
135
- "orders:manage",
136
- "cart:create",
137
- "cart:update",
138
- "cart:read",
139
- "cart:manage",
140
- "customers:update:self",
141
- "webhooks:manage",
142
- "pricing:manage",
143
- "shipping:manage",
144
- "tax:manage",
145
- "settings:manage",
146
- "analytics:read",
147
- "staff:manage",
148
- "promotions:manage",
149
- "promotions:read",
150
- "audit:read",
151
- "media:write",
152
- "compensation:admin",
153
- ],
154
- };
155
- /**
156
- * Test actor with read-only permissions
157
- */
158
- export const readonlyActor = {
159
- type: "user",
160
- userId: "00000000-0000-0000-0000-000000000002",
161
- email: "readonly@example.com",
162
- name: "Read Only User",
163
- vendorId: null,
164
- organizationId: "org_default",
165
- role: "customer",
166
- permissions: ["catalog:read", "cart:read", "orders:read:own"],
167
- };
168
- /**
169
- * Test actor with no permissions
170
- */
171
- export const noPermActor = {
172
- type: "user",
173
- userId: "00000000-0000-0000-0000-000000000003",
174
- email: "noperm@example.com",
175
- name: "No Perm",
176
- vendorId: null,
177
- organizationId: "org_default",
178
- role: "customer",
179
- permissions: [],
180
- };
181
114
  /**
182
115
  * Helper to create a mock request with actor context
183
116
  */
@@ -6,6 +6,15 @@ import type { Actor } from "../auth/types.js";
6
6
  * Better Auth API instead.
7
7
  */
8
8
  export declare const TEST_ORG_ID = "org_default";
9
+ /**
10
+ * A test actor in {@link TEST_ORG_ID}. Pass only what the test is about —
11
+ * usually `permissions` (and `role`); everything else has a stable default.
12
+ */
13
+ export declare function createTestActor(overrides?: Partial<Actor>): Actor;
14
+ /** Staff with the permissions the REST suites exercise. */
15
+ export declare const testActor: Actor;
16
+ /** Read-only shopper: browses and reads its own orders, cannot create a cart. */
17
+ export declare const readonlyActor: Actor;
9
18
  /** Admin with wildcard permissions. Use for setup operations in beforeAll. */
10
19
  export declare const testAdminActor: Actor;
11
20
  /** Staff with common operational permissions. */
@@ -1 +1 @@
1
- {"version":3,"file":"test-actors.d.ts","sourceRoot":"","sources":["../../src/test-utils/test-actors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAG9C;;;;;GAKG;AACH,eAAO,MAAM,WAAW,gBAAiB,CAAC;AAE1C,8EAA8E;AAC9E,eAAO,MAAM,cAAc,EAAE,KAS5B,CAAC;AAEF,iDAAiD;AACjD,eAAO,MAAM,cAAc,EAAE,KAY5B,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,iBAAiB,EAAE,KAS/B,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,eAAe,EAAE,KAS7B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAIjE"}
1
+ {"version":3,"file":"test-actors.d.ts","sourceRoot":"","sources":["../../src/test-utils/test-actors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAG9C;;;;;GAKG;AACH,eAAO,MAAM,WAAW,gBAAiB,CAAC;AAE1C;;;GAGG;AACH,wBAAgB,eAAe,CAAC,SAAS,GAAE,OAAO,CAAC,KAAK,CAAM,GAAG,KAAK,CAYrE;AAED,2DAA2D;AAC3D,eAAO,MAAM,SAAS,EAAE,KAmCtB,CAAC;AAEH,iFAAiF;AACjF,eAAO,MAAM,aAAa,EAAE,KAO1B,CAAC;AAEH,8EAA8E;AAC9E,eAAO,MAAM,cAAc,EAAE,KAS5B,CAAC;AAEF,iDAAiD;AACjD,eAAO,MAAM,cAAc,EAAE,KAY5B,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,iBAAiB,EAAE,KAS/B,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,eAAe,EAAE,KAS7B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAIjE"}
@@ -6,6 +6,68 @@ import { DEFAULT_ORG_ID } from "../auth/org.js";
6
6
  * Better Auth API instead.
7
7
  */
8
8
  export const TEST_ORG_ID = DEFAULT_ORG_ID;
9
+ /**
10
+ * A test actor in {@link TEST_ORG_ID}. Pass only what the test is about —
11
+ * usually `permissions` (and `role`); everything else has a stable default.
12
+ */
13
+ export function createTestActor(overrides = {}) {
14
+ return {
15
+ type: "user",
16
+ userId: "test-user-1",
17
+ email: "user@test.local",
18
+ name: "Test User",
19
+ vendorId: null,
20
+ organizationId: TEST_ORG_ID,
21
+ role: "staff",
22
+ permissions: [],
23
+ ...overrides,
24
+ };
25
+ }
26
+ /** Staff with the permissions the REST suites exercise. */
27
+ export const testActor = createTestActor({
28
+ userId: "00000000-0000-0000-0000-000000000001",
29
+ email: "test@example.com",
30
+ name: "Test Staff",
31
+ role: "staff",
32
+ permissions: [
33
+ "catalog:create",
34
+ "catalog:update",
35
+ "catalog:read",
36
+ "catalog:read:unpublished",
37
+ "inventory:adjust",
38
+ "inventory:read",
39
+ "orders:create",
40
+ "orders:create:on-behalf",
41
+ "orders:read",
42
+ "orders:update",
43
+ "orders:manage",
44
+ "cart:create",
45
+ "cart:update",
46
+ "cart:read",
47
+ "cart:manage",
48
+ "customers:update:self",
49
+ "webhooks:manage",
50
+ "pricing:manage",
51
+ "shipping:manage",
52
+ "tax:manage",
53
+ "settings:manage",
54
+ "analytics:read",
55
+ "staff:manage",
56
+ "promotions:manage",
57
+ "promotions:read",
58
+ "audit:read",
59
+ "media:write",
60
+ "compensation:admin",
61
+ ],
62
+ });
63
+ /** Read-only shopper: browses and reads its own orders, cannot create a cart. */
64
+ export const readonlyActor = createTestActor({
65
+ userId: "00000000-0000-0000-0000-000000000002",
66
+ email: "readonly@example.com",
67
+ name: "Read Only User",
68
+ role: "customer",
69
+ permissions: ["catalog:read", "cart:read", "orders:read:own"],
70
+ });
9
71
  /** Admin with wildcard permissions. Use for setup operations in beforeAll. */
10
72
  export const testAdminActor = {
11
73
  type: "user",
package/dist/testing.d.ts CHANGED
@@ -7,11 +7,8 @@
7
7
  */
8
8
  export { createTestKernel } from "./test-utils/create-test-kernel.js";
9
9
  export { createPGliteTestAdapter, type PGliteTestAdapter, type QueryLog } from "./test-utils/create-pglite-adapter.js";
10
- export { createTestPluginContext } from "./test-utils/create-test-plugin-context.js";
11
- export { createRepositoryTestHarness } from "./test-utils/create-repository-test-harness.js";
12
10
  export { createPluginTestApp, type PluginTestApp, type TestAppEnv } from "./test-utils/create-plugin-test-app.js";
13
- export { TEST_ORG_ID, testAdminActor, testStaffActor, testCustomerActor, testNoPermActor, jsonHeaders, } from "./test-utils/test-actors.js";
14
- export { beforeHook, afterHook } from "./test-utils/typed-hooks.js";
11
+ export { TEST_ORG_ID, createTestActor, testAdminActor, testStaffActor, testCustomerActor, testNoPermActor, jsonHeaders, } from "./test-utils/test-actors.js";
15
12
  export { markOrderPaidForTest } from "./test-utils/order-test-helpers.js";
16
13
  export { isInsideTransaction } from "./kernel/hooks/deferred.js";
17
14
  export { allowHookFailure, recordedHookFailures } from "./test-utils/hook-failures.js";
@@ -1 +1 @@
1
- {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAGtE,OAAO,EAAE,uBAAuB,EAAE,KAAK,iBAAiB,EAAE,KAAK,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AACvH,OAAO,EAAE,uBAAuB,EAAE,MAAM,4CAA4C,CAAC;AACrF,OAAO,EAAE,2BAA2B,EAAE,MAAM,gDAAgD,CAAC;AAC7F,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAClH,OAAO,EACL,WAAW,EACX,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,eAAe,EAClE,WAAW,GACZ,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAQ1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAMjE,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACvF,YAAY,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAG9D,YAAY,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAGtE,OAAO,EAAE,uBAAuB,EAAE,KAAK,iBAAiB,EAAE,KAAK,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AACvH,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAClH,OAAO,EACL,WAAW,EACX,eAAe,EACf,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,eAAe,EAClE,WAAW,GACZ,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAQ1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAMjE,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACvF,YAAY,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAG9D,YAAY,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/testing.js CHANGED
@@ -9,11 +9,8 @@ export { createTestKernel } from "./test-utils/create-test-kernel.js";
9
9
  // The query log is the only honest statement counter: the PGlite logger sees every statement core
10
10
  // issues, which a proxy around a plugin's own handle cannot.
11
11
  export { createPGliteTestAdapter } from "./test-utils/create-pglite-adapter.js";
12
- export { createTestPluginContext } from "./test-utils/create-test-plugin-context.js";
13
- export { createRepositoryTestHarness } from "./test-utils/create-repository-test-harness.js";
14
12
  export { createPluginTestApp } from "./test-utils/create-plugin-test-app.js";
15
- export { TEST_ORG_ID, testAdminActor, testStaffActor, testCustomerActor, testNoPermActor, jsonHeaders, } from "./test-utils/test-actors.js";
16
- export { beforeHook, afterHook } from "./test-utils/typed-hooks.js";
13
+ export { TEST_ORG_ID, createTestActor, testAdminActor, testStaffActor, testCustomerActor, testNoPermActor, jsonHeaders, } from "./test-utils/test-actors.js";
17
14
  export { markOrderPaidForTest } from "./test-utils/order-test-helpers.js";
18
15
  // The after-commit boundary predicate, so a suite can assert that the code under test really is
19
16
  // inside one. A plugin reaches the database through the `ctx.db` HANDLE, not the adapter, and the
@@ -0,0 +1,3 @@
1
+ /** Escape a value for interpolation into HTML text or a quoted attribute. */
2
+ export declare function escapeHtml(value: unknown): string;
3
+ //# sourceMappingURL=escape-html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape-html.d.ts","sourceRoot":"","sources":["../../src/utils/escape-html.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAOjD"}
@@ -0,0 +1,9 @@
1
+ /** Escape a value for interpolation into HTML text or a quoted attribute. */
2
+ export function escapeHtml(value) {
3
+ return String(value ?? "")
4
+ .replaceAll("&", "&amp;")
5
+ .replaceAll("<", "&lt;")
6
+ .replaceAll(">", "&gt;")
7
+ .replaceAll('"', "&quot;")
8
+ .replaceAll("'", "&#39;");
9
+ }
@@ -1,5 +1,4 @@
1
1
  import type { Actor } from "../auth/types.js";
2
- export declare function makeId(): string;
3
2
  export declare function makeDeterministicId(value: string): Promise<string>;
4
3
  export declare function makeIdempotencyScope(actor: Actor | null | undefined, guestCredential?: string, fallbackBinding?: string): Promise<string>;
5
4
  //# sourceMappingURL=id.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../../src/utils/id.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAE9C,wBAAgB,MAAM,IAAI,MAAM,CAE/B;AAED,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CASxE;AAED,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,KAAK,GAAG,IAAI,GAAG,SAAS,EAC/B,eAAe,CAAC,EAAE,MAAM,EACxB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,MAAM,CAAC,CAYjB"}
1
+ {"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../../src/utils/id.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAE9C,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CASxE;AAED,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,KAAK,GAAG,IAAI,GAAG,SAAS,EAC/B,eAAe,CAAC,EAAE,MAAM,EACxB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,MAAM,CAAC,CAYjB"}
package/dist/utils/id.js CHANGED
@@ -1,6 +1,3 @@
1
- export function makeId() {
2
- return crypto.randomUUID();
3
- }
4
1
  export async function makeDeterministicId(value) {
5
2
  const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value)));
6
3
  const bytes = digest.slice(0, 16);
@@ -1,3 +1,3 @@
1
1
  import type { Logger } from "../kernel/hooks/types.js";
2
- export declare function createLogger(scope: string): Logger;
2
+ export declare function createConsoleLogger(scope: string): Logger;
3
3
  //# sourceMappingURL=logger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAEvD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAelD"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAEvD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAezD"}
@@ -1,4 +1,4 @@
1
- export function createLogger(scope) {
1
+ export function createConsoleLogger(scope) {
2
2
  return {
3
3
  info(message, data) {
4
4
  // eslint-disable-next-line no-console
@@ -0,0 +1,13 @@
1
+ /** Number of minor-unit digits for an ISO 4217 code: 0 for JPY, 2 for USD. */
2
+ export declare function currencyExponent(currency: string): number;
3
+ /**
4
+ * A major-unit amount ("15.00", 15) as integer minor units in `currency`.
5
+ * Blank or non-numeric input answers `undefined` rather than 0, so a missing
6
+ * price is never mistaken for a free one.
7
+ */
8
+ export declare function toMinorUnits(amount: string | number | null | undefined, currency: string): number | undefined;
9
+ /** Minor units → "1,234.50 LKR" (or "1,500 JPY"). */
10
+ export declare function formatAmount(minor: number, currency: string): string;
11
+ /** An ISO 4217 code as stored: trimmed and upper-cased. */
12
+ export declare function normalizeCurrency(currency: string): string;
13
+ //# sourceMappingURL=money.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"money.d.ts","sourceRoot":"","sources":["../../src/utils/money.ts"],"names":[],"mappings":"AA2BA,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,EAC1C,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,SAAS,CAMpB;AAED,qDAAqD;AACrD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOpE;AAED,2DAA2D;AAC3D,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1D"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Currencies whose minor unit IS the major unit (ISO 4217 exponent 0), so an
3
+ * amount of 1500 JPY is stored as 1500, not 150000.
4
+ *
5
+ * ponytail: zero- vs two-decimal only. Three-decimal currencies (KWD, BHD, OMR,
6
+ * JOD, TND) are treated as two-decimal everywhere in core; give them exponent 3
7
+ * here once pricing and documents are audited for it.
8
+ */
9
+ const ZERO_DECIMAL_CURRENCIES = new Set([
10
+ "BIF",
11
+ "CLP",
12
+ "DJF",
13
+ "GNF",
14
+ "ISK",
15
+ "JPY",
16
+ "KMF",
17
+ "KRW",
18
+ "PYG",
19
+ "RWF",
20
+ "UGX",
21
+ "VND",
22
+ "VUV",
23
+ "XAF",
24
+ "XOF",
25
+ "XPF",
26
+ ]);
27
+ /** Number of minor-unit digits for an ISO 4217 code: 0 for JPY, 2 for USD. */
28
+ export function currencyExponent(currency) {
29
+ return ZERO_DECIMAL_CURRENCIES.has(currency.trim().toUpperCase()) ? 0 : 2;
30
+ }
31
+ /**
32
+ * A major-unit amount ("15.00", 15) as integer minor units in `currency`.
33
+ * Blank or non-numeric input answers `undefined` rather than 0, so a missing
34
+ * price is never mistaken for a free one.
35
+ */
36
+ export function toMinorUnits(amount, currency) {
37
+ if (amount == null)
38
+ return undefined;
39
+ if (typeof amount === "string" && amount.trim() === "")
40
+ return undefined;
41
+ const parsed = Number(amount);
42
+ if (!Number.isFinite(parsed))
43
+ return undefined;
44
+ return Math.round(parsed * 10 ** currencyExponent(currency));
45
+ }
46
+ /** Minor units → "1,234.50 LKR" (or "1,500 JPY"). */
47
+ export function formatAmount(minor, currency) {
48
+ const exponent = currencyExponent(currency);
49
+ const formatted = (minor / 10 ** exponent).toLocaleString("en-US", {
50
+ minimumFractionDigits: exponent,
51
+ maximumFractionDigits: exponent,
52
+ });
53
+ return `${formatted} ${currency}`;
54
+ }
55
+ /** An ISO 4217 code as stored: trimmed and upper-cased. */
56
+ export function normalizeCurrency(currency) {
57
+ return currency.trim().toUpperCase();
58
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@porulle/core",
3
- "version": "0.64.0",
3
+ "version": "0.65.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -62,8 +62,8 @@
62
62
  "eslint": "^9.39.1",
63
63
  "typescript": "5.9.2",
64
64
  "vitest": "^3.2.4",
65
- "@porulle/eslint-config": "0.1.0",
66
- "@porulle/typescript-config": "0.1.0"
65
+ "@porulle/typescript-config": "0.1.0",
66
+ "@porulle/eslint-config": "0.1.0"
67
67
  },
68
68
  "publishConfig": {
69
69
  "access": "public"
@@ -85,11 +85,10 @@
85
85
  },
86
86
  "author": "Porulle contributors",
87
87
  "scripts": {
88
- "generate:plugins": "node ./scripts/generate-plugin-types.mjs",
89
88
  "check:store-guard": "node ./scripts/check-store-guard.mjs",
90
89
  "check:auth-schema": "vitest run test/auth-schema-better-auth-parity.test.ts",
91
- "build": "rm -rf dist tsconfig.build.tsbuildinfo && npm run generate:plugins && npm run check:store-guard && npm run check:auth-schema && tsc -p tsconfig.build.json",
92
- "check-types": "npm run generate:plugins && npm run check:store-guard && tsc --noEmit",
90
+ "build": "rm -rf dist tsconfig.build.tsbuildinfo && npm run check:store-guard && npm run check:auth-schema && tsc -p tsconfig.build.json",
91
+ "check-types": "npm run check:store-guard && tsc --noEmit",
93
92
  "lint": "eslint . --max-warnings 1000",
94
93
  "test": "vitest run"
95
94
  }
@@ -0,0 +1,63 @@
1
+ import { escapeHtml } from "../utils/escape-html.js";
2
+
3
+ export type EmailData = Record<string, unknown>;
4
+ export type EmailTemplateMap = Record<string, (data: EmailData) => string>;
5
+
6
+ export interface RenderEmailOptions {
7
+ /** Subject line per template name; overrides the defaults below. Plain text, not HTML. */
8
+ subjects?: EmailTemplateMap;
9
+ /** HTML body per template name; overrides the defaults. Escape caller data with `escapeHtml`. */
10
+ templates?: EmailTemplateMap;
11
+ }
12
+
13
+ const shortId = (value: unknown) => escapeHtml(String(value).slice(0, 8));
14
+
15
+ const DEFAULT_SUBJECTS: EmailTemplateMap = {
16
+ "order-confirmation": (d) => `Order Confirmed${d.orderId ? ` - #${String(d.orderId).slice(0, 8)}` : ""}`,
17
+ "order-status-change": (d) => `Order Update - ${String(d.newStatus ?? "Status Changed")}`,
18
+ "password-reset": () => "Reset Your Password",
19
+ "email-verification": () => "Verify Your Email Address",
20
+ "appointment:reminder": (d) => `Appointment Reminder${d.reminderType === "1h" ? " - Starting Soon" : ""}`,
21
+ "appointment:confirmation-notice": () => "Appointment Confirmed",
22
+ "appointment:cancellation-notice": () => "Appointment Cancelled",
23
+ "appointment:no-show-notice": () => "Missed Appointment",
24
+ };
25
+
26
+ const DEFAULT_TEMPLATES: EmailTemplateMap = {
27
+ "order-confirmation": (d) =>
28
+ `<h2>Order Confirmed</h2><p>Thank you for your order${d.orderId ? ` <strong>#${shortId(d.orderId)}</strong>` : ""}.</p>${d.total ? `<p>Total: ${escapeHtml(d.currency ?? "USD")} ${escapeHtml(d.total)}</p>` : ""}`,
29
+ "order-status-change": (d) =>
30
+ `<h2>Order Update</h2><p>Your order${d.orderId ? ` <strong>#${shortId(d.orderId)}</strong>` : ""} status has been updated to <strong>${escapeHtml(d.newStatus ?? "unknown")}</strong>.</p>`,
31
+ "password-reset": (d) =>
32
+ `<h2>Reset Your Password</h2><p>Click the link below to reset your password:</p><p><a href="${escapeHtml(d.url ?? "#")}">Reset Password</a></p>`,
33
+ "email-verification": (d) =>
34
+ `<h2>Verify Your Email</h2><p>Click the link below to verify your email address:</p><p><a href="${escapeHtml(d.url ?? "#")}">Verify Email</a></p>`,
35
+ "appointment:reminder": (d) =>
36
+ `<h2>Appointment Reminder</h2><p>This is a${d.reminderType === "1h" ? " 1-hour" : " 24-hour"} reminder for your upcoming appointment.</p><p>Booking ID: ${escapeHtml(d.bookingId ?? "N/A")}</p>`,
37
+ "appointment:confirmation-notice": (d) =>
38
+ `<h2>Appointment Confirmed</h2><p>Your appointment has been confirmed.</p><p>Booking ID: ${escapeHtml(d.bookingId ?? "N/A")}</p>`,
39
+ "appointment:cancellation-notice": (d) =>
40
+ `<h2>Appointment Cancelled</h2><p>Your appointment has been cancelled.</p><p>Booking ID: ${escapeHtml(d.bookingId ?? "N/A")}</p>`,
41
+ "appointment:no-show-notice": (d) =>
42
+ `<h2>Missed Appointment</h2><p>You missed your appointment. Please contact us to rebook.</p><p>Booking ID: ${escapeHtml(d.bookingId ?? "N/A")}</p>`,
43
+ };
44
+
45
+ /**
46
+ * Subject and HTML body for a `config.email.send({ template, data })` call — the
47
+ * part every transport adapter (Resend, SES, …) shares. A template with no
48
+ * renderer falls back to a body listing its data.
49
+ */
50
+ export function renderEmail(
51
+ template: string,
52
+ data: EmailData,
53
+ options: RenderEmailOptions = {},
54
+ ): { subject: string; html: string } {
55
+ const subject = options.subjects?.[template] ?? DEFAULT_SUBJECTS[template];
56
+ const body = options.templates?.[template] ?? DEFAULT_TEMPLATES[template];
57
+ return {
58
+ subject: subject ? subject(data) : template,
59
+ html: body
60
+ ? body(data)
61
+ : `<p>Notification: ${escapeHtml(template)}</p><pre>${escapeHtml(JSON.stringify(data, null, 2))}</pre>`,
62
+ };
63
+ }
package/src/auth/actor.ts CHANGED
@@ -3,6 +3,8 @@ import type { Actor } from "./types.js";
3
3
  import type { AuthInstance } from "./setup.js";
4
4
  import { DEFAULT_ORG_ID } from "./org.js";
5
5
  import { isCredentialRejection } from "./auth-failure.js";
6
+ import { CommerceTwoFactorRequiredError } from "../kernel/errors.js";
7
+ import { roleParts } from "./role-authority.js";
6
8
 
7
9
  /**
8
10
  * The slice of Better Auth's internal context this file uses. Declared here
@@ -137,6 +139,18 @@ export async function resolveActor(
137
139
  }
138
140
  }
139
141
 
142
+ // A role that must prove a second factor gets nothing until the member has
143
+ // enrolled. Refused outright rather than served as a customer, so the client
144
+ // can tell the member why and where to enrol.
145
+ // Better Auth stores a member's role as a comma-separated list, so "owner,admin"
146
+ // holds "owner": any listed part requires the second factor.
147
+ const requiredForRoles = config.auth?.twoFactor?.requiredForRoles ?? [];
148
+ if (roleParts(role).some((part) => requiredForRoles.includes(part)) && session.user.twoFactorEnabled !== true) {
149
+ throw new CommerceTwoFactorRequiredError(
150
+ `The "${role}" role requires two-factor authentication. Enable it at /api/auth/two-factor/enable, then sign in again.`,
151
+ );
152
+ }
153
+
140
154
  return {
141
155
  type: "user",
142
156
  userId: session.user.id,
@@ -16,8 +16,3 @@ export function isCredentialRejection(err: unknown): err is { name: "APIError";
16
16
  const { name, statusCode } = err as { name?: unknown; statusCode?: unknown };
17
17
  return name === "APIError" && typeof statusCode === "number";
18
18
  }
19
-
20
- /** The HTTP status better-auth attached to a credential rejection, or null for anything else. */
21
- export function credentialRejectionStatus(err: unknown): number | null {
22
- return isCredentialRejection(err) ? err.statusCode : null;
23
- }
@@ -4,18 +4,15 @@ import type { Actor } from "./types.js";
4
4
  import type { AuthInstance } from "./setup.js";
5
5
  import { getCustomerPermissions, resolveActor } from "./actor.js";
6
6
  import { DEFAULT_ORG_ID } from "./org.js";
7
- import { credentialRejectionStatus, isCredentialRejection } from "./auth-failure.js";
7
+ import { isCredentialRejection } from "./auth-failure.js";
8
8
  import { isStrictOrgResolution } from "./strict-org-resolution.js";
9
9
  import { isIdentityFreeRoute } from "./identity-free-routes.js";
10
+ import { CommerceTwoFactorRequiredError } from "../kernel/errors.js";
10
11
 
11
12
  function emptyToNull(value: string | null | undefined): string | null {
12
13
  return value == null || value === "" ? null : value;
13
14
  }
14
15
 
15
- // Exported so the storefront contract can be pinned by a test: an anonymous
16
- // visitor resolved by `storeResolver` gets these permissions, so dropping
17
- // `catalog:read` here would 401 every public storefront read.
18
- export { DEFAULT_CUSTOMER_PERMISSIONS } from "./actor.js";
19
16
 
20
17
  /**
21
18
  * The challenge RFC 9110 §15.5.2 requires on a 401: it "MUST include a WWW-Authenticate header
@@ -100,6 +97,10 @@ export function authMiddleware(
100
97
  try {
101
98
  actor = await resolveActor(c.req.raw.headers, auth, config, c.req.raw);
102
99
  } catch (err) {
100
+ // An evaluated credential that the role policy refuses — not a fault.
101
+ if (err instanceof CommerceTwoFactorRequiredError) {
102
+ return c.json({ error: { code: err.code, message: err.message } }, 403);
103
+ }
103
104
  reportAuthCheckFault(err, "session");
104
105
  throw err;
105
106
  }
@@ -214,7 +215,7 @@ export function authMiddleware(
214
215
  reportAuthCheckFault(err, "api_key");
215
216
  throw err;
216
217
  }
217
- if (credentialRejectionStatus(err) === 429) {
218
+ if (err.statusCode === 429) {
218
219
  return c.json({ error: { code: "RATE_LIMITED", message: "Too many requests for this credential." } }, 429);
219
220
  }
220
221
  }
@@ -17,13 +17,19 @@ export function isUnauthenticatedActor(
17
17
  return actor === null || (actor.type === "user" && actor.userId === null);
18
18
  }
19
19
 
20
- export function hasPermission(actor: Actor | null, required: string): boolean {
21
- if (!actor) return false;
22
- if (actor.permissions.includes("*:*")) return true;
23
-
20
+ /** Whether a permission list grants `required`: an exact entry, `resource:*`, or `*:*`. */
21
+ export function hasPermissionFromList(
22
+ granted: readonly string[],
23
+ required: string,
24
+ ): boolean {
25
+ if (granted.includes("*:*")) return true;
24
26
  const [resource] = required.split(":");
25
- if (resource && actor.permissions.includes(`${resource}:*`)) return true;
26
- return actor.permissions.includes(required);
27
+ if (resource && granted.includes(`${resource}:*`)) return true;
28
+ return granted.includes(required);
29
+ }
30
+
31
+ export function hasPermission(actor: Actor | null, required: string): boolean {
32
+ return actor !== null && hasPermissionFromList(actor.permissions, required);
27
33
  }
28
34
 
29
35
  export function assertPermission(actor: Actor | null, required: string): void {
@@ -1,4 +1,5 @@
1
1
  import type { CommerceConfig } from "../config/types.js";
2
+ import { hasPermissionFromList } from "./permissions.js";
2
3
 
3
4
  const BUILTIN_ROLE_RANK: Record<string, number> = {
4
5
  owner: 3,
@@ -42,16 +43,6 @@ export function permissionsForRole(config: CommerceConfig, role: string): string
42
43
  return config.auth?.roles?.[role]?.permissions ?? [];
43
44
  }
44
45
 
45
- export function hasPermissionFromList(
46
- actorPermissions: readonly string[],
47
- required: string,
48
- ): boolean {
49
- if (actorPermissions.includes("*:*")) return true;
50
-
51
- const [resource] = required.split(":");
52
- if (resource && actorPermissions.includes(`${resource}:*`)) return true;
53
- return actorPermissions.includes(required);
54
- }
55
46
 
56
47
  /**
57
48
  * The role's privilege rank. A composite role ranks as its strongest part, so
package/src/auth/setup.ts CHANGED
@@ -91,6 +91,14 @@ export function createAuth(
91
91
  jwt(),
92
92
  ];
93
93
 
94
+ // Requiring a second factor while the plugin that enrols one is off would lock
95
+ // every listed role out with no way back in.
96
+ if ((config.auth?.twoFactor?.requiredForRoles?.length ?? 0) > 0 && !config.auth?.twoFactor?.enabled) {
97
+ throw new Error(
98
+ "auth.twoFactor.requiredForRoles needs auth.twoFactor.enabled: true — members of those roles could never enrol.",
99
+ );
100
+ }
101
+
94
102
  if (config.auth?.twoFactor?.enabled) {
95
103
  plugins.push(twoFactor({ issuer: config.storeName ?? "UnifiedCommerce" }));
96
104
  }