@porulle/core 0.7.0 → 0.9.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 (325) hide show
  1. package/dist/auth/middleware.d.ts.map +1 -1
  2. package/dist/auth/middleware.js +26 -7
  3. package/dist/auth/setup.d.ts.map +1 -1
  4. package/dist/auth/setup.js +8 -5
  5. package/dist/config/defaults.d.ts.map +1 -1
  6. package/dist/config/defaults.js +7 -0
  7. package/dist/config/types.d.ts +26 -1
  8. package/dist/config/types.d.ts.map +1 -1
  9. package/dist/generated/plugin-manifest.d.ts +3 -0
  10. package/dist/generated/plugin-manifest.d.ts.map +1 -1
  11. package/dist/generated/plugin-manifest.js +1 -0
  12. package/dist/hooks/checkout-completion.d.ts.map +1 -1
  13. package/dist/hooks/checkout-completion.js +2 -2
  14. package/dist/hooks/checkout.d.ts.map +1 -1
  15. package/dist/hooks/checkout.js +17 -2
  16. package/dist/index.d.ts +1 -0
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +1 -0
  19. package/dist/interfaces/rest/index.d.ts.map +1 -1
  20. package/dist/interfaces/rest/index.js +12 -0
  21. package/dist/interfaces/rest/routes/admin/staff.d.ts +12 -0
  22. package/dist/interfaces/rest/routes/admin/staff.d.ts.map +1 -0
  23. package/dist/interfaces/rest/routes/admin/staff.js +206 -0
  24. package/dist/interfaces/rest/routes/analytics.d.ts +5 -0
  25. package/dist/interfaces/rest/routes/analytics.d.ts.map +1 -0
  26. package/dist/interfaces/rest/routes/analytics.js +24 -0
  27. package/dist/interfaces/rest/routes/carts.d.ts.map +1 -1
  28. package/dist/interfaces/rest/routes/carts.js +39 -2
  29. package/dist/interfaces/rest/routes/catalog.d.ts.map +1 -1
  30. package/dist/interfaces/rest/routes/catalog.js +17 -1
  31. package/dist/interfaces/rest/routes/checkout.d.ts +9 -0
  32. package/dist/interfaces/rest/routes/checkout.d.ts.map +1 -1
  33. package/dist/interfaces/rest/routes/checkout.js +97 -21
  34. package/dist/interfaces/rest/routes/documents.d.ts +10 -0
  35. package/dist/interfaces/rest/routes/documents.d.ts.map +1 -0
  36. package/dist/interfaces/rest/routes/documents.js +40 -0
  37. package/dist/interfaces/rest/routes/inventory.d.ts.map +1 -1
  38. package/dist/interfaces/rest/routes/inventory.js +13 -0
  39. package/dist/interfaces/rest/routes/orders.d.ts.map +1 -1
  40. package/dist/interfaces/rest/routes/orders.js +111 -1
  41. package/dist/interfaces/rest/routes/pricing.d.ts.map +1 -1
  42. package/dist/interfaces/rest/routes/pricing.js +36 -1
  43. package/dist/interfaces/rest/routes/settings.d.ts +5 -0
  44. package/dist/interfaces/rest/routes/settings.d.ts.map +1 -0
  45. package/dist/interfaces/rest/routes/settings.js +50 -0
  46. package/dist/interfaces/rest/routes/shipping.d.ts +5 -0
  47. package/dist/interfaces/rest/routes/shipping.d.ts.map +1 -0
  48. package/dist/interfaces/rest/routes/shipping.js +68 -0
  49. package/dist/interfaces/rest/routes/tax.d.ts +5 -0
  50. package/dist/interfaces/rest/routes/tax.d.ts.map +1 -0
  51. package/dist/interfaces/rest/routes/tax.js +68 -0
  52. package/dist/interfaces/rest/schemas/admin-staff.d.ts +899 -0
  53. package/dist/interfaces/rest/schemas/admin-staff.d.ts.map +1 -0
  54. package/dist/interfaces/rest/schemas/admin-staff.js +98 -0
  55. package/dist/interfaces/rest/schemas/analytics.d.ts +252 -0
  56. package/dist/interfaces/rest/schemas/analytics.d.ts.map +1 -0
  57. package/dist/interfaces/rest/schemas/analytics.js +33 -0
  58. package/dist/interfaces/rest/schemas/carts.d.ts +656 -0
  59. package/dist/interfaces/rest/schemas/carts.d.ts.map +1 -1
  60. package/dist/interfaces/rest/schemas/carts.js +38 -0
  61. package/dist/interfaces/rest/schemas/catalog.d.ts +1218 -1
  62. package/dist/interfaces/rest/schemas/catalog.d.ts.map +1 -1
  63. package/dist/interfaces/rest/schemas/catalog.js +48 -0
  64. package/dist/interfaces/rest/schemas/checkout.d.ts +2 -0
  65. package/dist/interfaces/rest/schemas/checkout.d.ts.map +1 -1
  66. package/dist/interfaces/rest/schemas/checkout.js +4 -0
  67. package/dist/interfaces/rest/schemas/customer-portal.d.ts +35 -0
  68. package/dist/interfaces/rest/schemas/customer-portal.d.ts.map +1 -1
  69. package/dist/interfaces/rest/schemas/documents.d.ts +509 -0
  70. package/dist/interfaces/rest/schemas/documents.d.ts.map +1 -0
  71. package/dist/interfaces/rest/schemas/documents.js +65 -0
  72. package/dist/interfaces/rest/schemas/orders.d.ts +3110 -43
  73. package/dist/interfaces/rest/schemas/orders.d.ts.map +1 -1
  74. package/dist/interfaces/rest/schemas/orders.js +234 -1
  75. package/dist/interfaces/rest/schemas/pricing.d.ts +405 -0
  76. package/dist/interfaces/rest/schemas/pricing.d.ts.map +1 -1
  77. package/dist/interfaces/rest/schemas/pricing.js +70 -0
  78. package/dist/interfaces/rest/schemas/responses.d.ts +190 -0
  79. package/dist/interfaces/rest/schemas/responses.d.ts.map +1 -1
  80. package/dist/interfaces/rest/schemas/search.d.ts +17 -0
  81. package/dist/interfaces/rest/schemas/search.d.ts.map +1 -1
  82. package/dist/interfaces/rest/schemas/settings.d.ts +397 -0
  83. package/dist/interfaces/rest/schemas/settings.d.ts.map +1 -0
  84. package/dist/interfaces/rest/schemas/settings.js +79 -0
  85. package/dist/interfaces/rest/schemas/shipping.d.ts +1093 -0
  86. package/dist/interfaces/rest/schemas/shipping.d.ts.map +1 -0
  87. package/dist/interfaces/rest/schemas/shipping.js +146 -0
  88. package/dist/interfaces/rest/schemas/tax.d.ts +1074 -0
  89. package/dist/interfaces/rest/schemas/tax.d.ts.map +1 -0
  90. package/dist/interfaces/rest/schemas/tax.js +132 -0
  91. package/dist/kernel/database/schema.d.ts +4 -0
  92. package/dist/kernel/database/schema.d.ts.map +1 -1
  93. package/dist/kernel/database/schema.js +8 -0
  94. package/dist/kernel/database/scoped-db.d.ts +2 -1
  95. package/dist/kernel/database/scoped-db.d.ts.map +1 -1
  96. package/dist/kernel/database/scoped-db.js +62 -1
  97. package/dist/kernel/hooks/types.d.ts +1 -1
  98. package/dist/kernel/hooks/types.d.ts.map +1 -1
  99. package/dist/kernel/plugin/manifest.d.ts +26 -0
  100. package/dist/kernel/plugin/manifest.d.ts.map +1 -1
  101. package/dist/kernel/plugin/manifest.js +17 -2
  102. package/dist/modules/analytics/drizzle-adapter.d.ts.map +1 -1
  103. package/dist/modules/analytics/drizzle-adapter.js +16 -3
  104. package/dist/modules/analytics/module.d.ts.map +1 -1
  105. package/dist/modules/analytics/module.js +6 -0
  106. package/dist/modules/analytics/reports.d.ts +58 -0
  107. package/dist/modules/analytics/reports.d.ts.map +1 -0
  108. package/dist/modules/analytics/reports.js +249 -0
  109. package/dist/modules/analytics/service.d.ts +10 -0
  110. package/dist/modules/analytics/service.d.ts.map +1 -1
  111. package/dist/modules/analytics/service.js +14 -0
  112. package/dist/modules/cart/repository/index.d.ts +7 -0
  113. package/dist/modules/cart/repository/index.d.ts.map +1 -1
  114. package/dist/modules/cart/repository/index.js +25 -1
  115. package/dist/modules/cart/schema.d.ts +17 -0
  116. package/dist/modules/cart/schema.d.ts.map +1 -1
  117. package/dist/modules/cart/schema.js +2 -0
  118. package/dist/modules/cart/schemas.d.ts +1 -0
  119. package/dist/modules/cart/schemas.d.ts.map +1 -1
  120. package/dist/modules/cart/schemas.js +1 -0
  121. package/dist/modules/cart/service.d.ts +32 -0
  122. package/dist/modules/cart/service.d.ts.map +1 -1
  123. package/dist/modules/cart/service.js +61 -2
  124. package/dist/modules/catalog/entity-service.d.ts +21 -0
  125. package/dist/modules/catalog/entity-service.d.ts.map +1 -1
  126. package/dist/modules/catalog/entity-service.js +166 -5
  127. package/dist/modules/catalog/schema.d.ts +34 -0
  128. package/dist/modules/catalog/schema.d.ts.map +1 -1
  129. package/dist/modules/catalog/schema.js +5 -0
  130. package/dist/modules/catalog/schemas.d.ts +3 -0
  131. package/dist/modules/catalog/schemas.d.ts.map +1 -1
  132. package/dist/modules/catalog/schemas.js +3 -0
  133. package/dist/modules/catalog/service.d.ts +36 -0
  134. package/dist/modules/catalog/service.d.ts.map +1 -1
  135. package/dist/modules/catalog/service.js +6 -0
  136. package/dist/modules/customers/service.d.ts.map +1 -1
  137. package/dist/modules/customers/service.js +6 -0
  138. package/dist/modules/documents/module.d.ts +7 -0
  139. package/dist/modules/documents/module.d.ts.map +1 -0
  140. package/dist/modules/documents/module.js +12 -0
  141. package/dist/modules/documents/pdf.d.ts +25 -0
  142. package/dist/modules/documents/pdf.d.ts.map +1 -0
  143. package/dist/modules/documents/pdf.js +80 -0
  144. package/dist/modules/documents/render.d.ts +32 -0
  145. package/dist/modules/documents/render.d.ts.map +1 -0
  146. package/dist/modules/documents/render.js +190 -0
  147. package/dist/modules/documents/repository/index.d.ts +25 -0
  148. package/dist/modules/documents/repository/index.d.ts.map +1 -0
  149. package/dist/modules/documents/repository/index.js +47 -0
  150. package/dist/modules/documents/schema.d.ts +214 -0
  151. package/dist/modules/documents/schema.d.ts.map +1 -0
  152. package/dist/modules/documents/schema.js +42 -0
  153. package/dist/modules/documents/service.d.ts +51 -0
  154. package/dist/modules/documents/service.d.ts.map +1 -0
  155. package/dist/modules/documents/service.js +119 -0
  156. package/dist/modules/fulfillment/service.d.ts +18 -0
  157. package/dist/modules/fulfillment/service.d.ts.map +1 -1
  158. package/dist/modules/fulfillment/service.js +85 -1
  159. package/dist/modules/orders/repository/index.d.ts +18 -1
  160. package/dist/modules/orders/repository/index.d.ts.map +1 -1
  161. package/dist/modules/orders/repository/index.js +86 -1
  162. package/dist/modules/orders/schema.d.ts +391 -0
  163. package/dist/modules/orders/schema.d.ts.map +1 -1
  164. package/dist/modules/orders/schema.js +56 -1
  165. package/dist/modules/orders/service.d.ts +102 -3
  166. package/dist/modules/orders/service.d.ts.map +1 -1
  167. package/dist/modules/orders/service.js +653 -29
  168. package/dist/modules/orders/stale-order-cleanup.d.ts.map +1 -1
  169. package/dist/modules/orders/stale-order-cleanup.js +13 -1
  170. package/dist/modules/pricing/repository/index.d.ts +5 -0
  171. package/dist/modules/pricing/repository/index.d.ts.map +1 -1
  172. package/dist/modules/pricing/repository/index.js +19 -0
  173. package/dist/modules/pricing/service.d.ts +18 -0
  174. package/dist/modules/pricing/service.d.ts.map +1 -1
  175. package/dist/modules/pricing/service.js +43 -5
  176. package/dist/modules/settings/module.d.ts +6 -0
  177. package/dist/modules/settings/module.d.ts.map +1 -0
  178. package/dist/modules/settings/module.js +11 -0
  179. package/dist/modules/settings/repository/index.d.ts +16 -0
  180. package/dist/modules/settings/repository/index.d.ts.map +1 -0
  181. package/dist/modules/settings/repository/index.js +41 -0
  182. package/dist/modules/settings/schema.d.ts +121 -0
  183. package/dist/modules/settings/schema.d.ts.map +1 -0
  184. package/dist/modules/settings/schema.js +24 -0
  185. package/dist/modules/settings/service.d.ts +26 -0
  186. package/dist/modules/settings/service.d.ts.map +1 -0
  187. package/dist/modules/settings/service.js +51 -0
  188. package/dist/modules/shipping/calculator.d.ts +5 -0
  189. package/dist/modules/shipping/calculator.d.ts.map +1 -1
  190. package/dist/modules/shipping/calculator.js +10 -0
  191. package/dist/modules/shipping/module.d.ts +5 -1
  192. package/dist/modules/shipping/module.d.ts.map +1 -1
  193. package/dist/modules/shipping/module.js +4 -1
  194. package/dist/modules/shipping/repository/index.d.ts +27 -2
  195. package/dist/modules/shipping/repository/index.d.ts.map +1 -1
  196. package/dist/modules/shipping/repository/index.js +105 -1
  197. package/dist/modules/shipping/schema.d.ts +419 -0
  198. package/dist/modules/shipping/schema.d.ts.map +1 -0
  199. package/dist/modules/shipping/schema.js +56 -0
  200. package/dist/modules/shipping/service.d.ts +54 -0
  201. package/dist/modules/shipping/service.d.ts.map +1 -1
  202. package/dist/modules/shipping/service.js +161 -2
  203. package/dist/modules/tax/adapter.d.ts +13 -0
  204. package/dist/modules/tax/adapter.d.ts.map +1 -1
  205. package/dist/modules/tax/module.d.ts +5 -1
  206. package/dist/modules/tax/module.d.ts.map +1 -1
  207. package/dist/modules/tax/module.js +4 -1
  208. package/dist/modules/tax/repository/index.d.ts +38 -2
  209. package/dist/modules/tax/repository/index.d.ts.map +1 -1
  210. package/dist/modules/tax/repository/index.js +138 -1
  211. package/dist/modules/tax/schema.d.ts +355 -0
  212. package/dist/modules/tax/schema.d.ts.map +1 -0
  213. package/dist/modules/tax/schema.js +55 -0
  214. package/dist/modules/tax/service.d.ts +60 -1
  215. package/dist/modules/tax/service.d.ts.map +1 -1
  216. package/dist/modules/tax/service.js +227 -2
  217. package/dist/runtime/kernel-modules.d.ts +15 -2
  218. package/dist/runtime/kernel-modules.d.ts.map +1 -1
  219. package/dist/runtime/kernel-modules.js +4 -0
  220. package/dist/runtime/kernel-types.d.ts +5 -1
  221. package/dist/runtime/kernel-types.d.ts.map +1 -1
  222. package/dist/runtime/kernel-types.js +2 -0
  223. package/dist/runtime/server.js +1 -1
  224. package/dist/test-utils/create-plugin-test-app.d.ts +3 -0
  225. package/dist/test-utils/create-plugin-test-app.d.ts.map +1 -1
  226. package/dist/test-utils/create-plugin-test-app.js +15 -3
  227. package/dist/test-utils/create-test-config.d.ts.map +1 -1
  228. package/dist/test-utils/create-test-config.js +2 -0
  229. package/dist/test-utils/order-test-helpers.d.ts +12 -0
  230. package/dist/test-utils/order-test-helpers.d.ts.map +1 -0
  231. package/dist/test-utils/order-test-helpers.js +18 -0
  232. package/dist/test-utils/rest-api-test-utils.d.ts.map +1 -1
  233. package/dist/test-utils/rest-api-test-utils.js +7 -0
  234. package/dist/test-utils/test-actors.js +1 -1
  235. package/dist/testing.d.ts +1 -0
  236. package/dist/testing.d.ts.map +1 -1
  237. package/dist/testing.js +1 -0
  238. package/package.json +3 -3
  239. package/src/auth/middleware.ts +26 -7
  240. package/src/auth/setup.ts +11 -4
  241. package/src/config/defaults.ts +7 -0
  242. package/src/config/types.ts +26 -1
  243. package/src/generated/plugin-capabilities.d.ts +1 -0
  244. package/src/generated/plugin-manifest.ts +1 -0
  245. package/src/generated/plugin-repositories.d.ts +1 -0
  246. package/src/hooks/checkout-completion.ts +22 -16
  247. package/src/hooks/checkout.ts +36 -11
  248. package/src/index.ts +1 -0
  249. package/src/interfaces/rest/index.ts +12 -0
  250. package/src/interfaces/rest/routes/admin/staff.ts +260 -0
  251. package/src/interfaces/rest/routes/analytics.ts +33 -0
  252. package/src/interfaces/rest/routes/carts.ts +52 -2
  253. package/src/interfaces/rest/routes/catalog.ts +34 -0
  254. package/src/interfaces/rest/routes/checkout.ts +114 -27
  255. package/src/interfaces/rest/routes/documents.ts +61 -0
  256. package/src/interfaces/rest/routes/inventory.ts +14 -0
  257. package/src/interfaces/rest/routes/orders.ts +148 -1
  258. package/src/interfaces/rest/routes/pricing.ts +44 -1
  259. package/src/interfaces/rest/routes/settings.ts +61 -0
  260. package/src/interfaces/rest/routes/shipping.ts +92 -0
  261. package/src/interfaces/rest/routes/tax.ts +90 -0
  262. package/src/interfaces/rest/schemas/admin-staff.ts +110 -0
  263. package/src/interfaces/rest/schemas/analytics.ts +39 -0
  264. package/src/interfaces/rest/schemas/carts.ts +40 -0
  265. package/src/interfaces/rest/schemas/catalog.ts +53 -0
  266. package/src/interfaces/rest/schemas/checkout.ts +4 -0
  267. package/src/interfaces/rest/schemas/documents.ts +72 -0
  268. package/src/interfaces/rest/schemas/orders.ts +258 -1
  269. package/src/interfaces/rest/schemas/pricing.ts +75 -0
  270. package/src/interfaces/rest/schemas/settings.ts +93 -0
  271. package/src/interfaces/rest/schemas/shipping.ts +164 -0
  272. package/src/interfaces/rest/schemas/tax.ts +148 -0
  273. package/src/kernel/database/schema.ts +12 -0
  274. package/src/kernel/database/scoped-db.ts +70 -1
  275. package/src/kernel/hooks/types.ts +1 -0
  276. package/src/kernel/plugin/manifest.ts +41 -2
  277. package/src/modules/analytics/drizzle-adapter.ts +19 -3
  278. package/src/modules/analytics/module.ts +10 -0
  279. package/src/modules/analytics/reports.ts +311 -0
  280. package/src/modules/analytics/service.ts +23 -0
  281. package/src/modules/cart/repository/index.ts +30 -1
  282. package/src/modules/cart/schema.ts +2 -0
  283. package/src/modules/cart/schemas.ts +1 -0
  284. package/src/modules/cart/service.ts +104 -2
  285. package/src/modules/catalog/entity-service.ts +196 -4
  286. package/src/modules/catalog/schema.ts +5 -0
  287. package/src/modules/catalog/schemas.ts +3 -0
  288. package/src/modules/catalog/service.ts +30 -0
  289. package/src/modules/customers/service.ts +6 -0
  290. package/src/modules/documents/module.ts +19 -0
  291. package/src/modules/documents/pdf.ts +101 -0
  292. package/src/modules/documents/render.ts +231 -0
  293. package/src/modules/documents/repository/index.ts +68 -0
  294. package/src/modules/documents/schema.ts +44 -0
  295. package/src/modules/documents/service.ts +176 -0
  296. package/src/modules/fulfillment/service.ts +139 -1
  297. package/src/modules/orders/repository/index.ts +127 -1
  298. package/src/modules/orders/schema.ts +58 -1
  299. package/src/modules/orders/service.ts +1041 -65
  300. package/src/modules/orders/stale-order-cleanup.ts +18 -4
  301. package/src/modules/pricing/repository/index.ts +34 -0
  302. package/src/modules/pricing/service.ts +76 -6
  303. package/src/modules/settings/module.ts +18 -0
  304. package/src/modules/settings/repository/index.ts +59 -0
  305. package/src/modules/settings/schema.ts +25 -0
  306. package/src/modules/settings/service.ts +82 -0
  307. package/src/modules/shipping/calculator.ts +27 -0
  308. package/src/modules/shipping/module.ts +6 -2
  309. package/src/modules/shipping/repository/index.ts +136 -2
  310. package/src/modules/shipping/schema.ts +58 -0
  311. package/src/modules/shipping/service.ts +260 -1
  312. package/src/modules/tax/adapter.ts +9 -0
  313. package/src/modules/tax/module.ts +6 -2
  314. package/src/modules/tax/repository/index.ts +169 -2
  315. package/src/modules/tax/schema.ts +57 -0
  316. package/src/modules/tax/service.ts +313 -2
  317. package/src/runtime/kernel-modules.ts +4 -0
  318. package/src/runtime/kernel-types.ts +6 -0
  319. package/src/runtime/server.ts +1 -1
  320. package/src/test-utils/create-plugin-test-app.ts +17 -4
  321. package/src/test-utils/create-test-config.ts +2 -0
  322. package/src/test-utils/order-test-helpers.ts +26 -0
  323. package/src/test-utils/rest-api-test-utils.ts +7 -0
  324. package/src/test-utils/test-actors.ts +1 -1
  325. package/src/testing.ts +1 -0
@@ -1,11 +1,53 @@
1
- import { CommerceValidationError } from "../../kernel/errors.js";
1
+ import { resolveOrgId } from "../../auth/org.js";
2
+ import { CommerceNotFoundError, CommerceValidationError } from "../../kernel/errors.js";
2
3
  import { Err, Ok } from "../../kernel/result.js";
3
4
  export class TaxService {
4
5
  adapter;
6
+ repository;
5
7
  constructor(deps) {
6
8
  this.adapter = deps.adapter;
9
+ this.repository = deps.repository;
7
10
  }
8
- async calculate(params) {
11
+ /**
12
+ * Calculates tax. Resolution order:
13
+ * 1. Product tax classes (issue #57) — when the org defines active classes,
14
+ * each line taxes by its class (variant taxClass beats entity taxClass;
15
+ * unclassed lines use the default class or 0), with `orderDiscount`
16
+ * pro-rated across lines first. Returns per-line results in `lines`.
17
+ * 2. Runtime tax rates for the org matching `toAddress` (issue #45) —
18
+ * state-specific matches beat country-level; matches at the winning
19
+ * specificity are summed (e.g. GST + PST).
20
+ * 3. The configured tax adapter.
21
+ * 4. Zero tax.
22
+ */
23
+ async calculate(params, orgId, ctx) {
24
+ if (this.repository && orgId && params.lineItems.length > 0) {
25
+ const classes = await this.repository.findActiveClasses(orgId, ctx);
26
+ if (classes.length > 0) {
27
+ return Ok(await this.calculateByClasses(params, classes, ctx));
28
+ }
29
+ }
30
+ if (this.repository && orgId && params.toAddress) {
31
+ const matched = await this.matchRuntimeRates(orgId, params.toAddress, ctx);
32
+ if (matched.length > 0) {
33
+ const taxableAmount = params.lineItems.reduce((sum, lineItem) => sum + lineItem.unitPrice * lineItem.quantity - (lineItem.discount ?? 0), 0);
34
+ let amountToCollect = 0;
35
+ const breakdown = {};
36
+ for (const rate of matched) {
37
+ const base = taxableAmount + (rate.appliesToShipping ? params.shippingAmount : 0);
38
+ const amount = Math.max(0, Math.round((base * rate.rateBps) / 10_000));
39
+ amountToCollect += amount;
40
+ breakdown[rate.name] = { rateBps: rate.rateBps, amount };
41
+ }
42
+ const totalBps = matched.reduce((sum, r) => sum + r.rateBps, 0);
43
+ return Ok({
44
+ amountToCollect,
45
+ taxableAmount,
46
+ rate: totalBps / 10_000,
47
+ breakdown,
48
+ });
49
+ }
50
+ }
9
51
  if (!this.adapter) {
10
52
  return Ok({
11
53
  amountToCollect: 0,
@@ -15,6 +57,123 @@ export class TaxService {
15
57
  }
16
58
  return this.adapter.calculateTax(params);
17
59
  }
60
+ /** Per-line class-based tax with cart-discount pro-ration (issue #57). */
61
+ async calculateByClasses(params, classes, ctx) {
62
+ const byName = new Map(classes.map((c) => [c.name, c]));
63
+ const defaultClass = classes.find((c) => c.isDefault) ?? null;
64
+ const { byEntity, byVariant } = await this.repository.resolveCatalogTaxClasses(params.lineItems.map((li) => ({ entityId: li.entityId, variantId: li.variantId })), ctx);
65
+ // Pro-rate the cart-level discount across lines by value share; the last
66
+ // line absorbs the rounding remainder so the sum stays exact.
67
+ const lineValues = params.lineItems.map((li) => Math.max(0, li.unitPrice * li.quantity - (li.discount ?? 0)));
68
+ const totalValue = lineValues.reduce((sum, v) => sum + v, 0);
69
+ const orderDiscount = Math.min(params.orderDiscount ?? 0, totalValue);
70
+ const prorated = lineValues.map((value) => totalValue > 0 ? Math.round((orderDiscount * value) / totalValue) : 0);
71
+ if (lineValues.length > 0) {
72
+ const drift = orderDiscount - prorated.reduce((sum, v) => sum + v, 0);
73
+ prorated[prorated.length - 1] += drift;
74
+ }
75
+ let amountToCollect = 0;
76
+ let taxableAmount = 0;
77
+ const breakdown = {};
78
+ const lines = [];
79
+ for (const [i, lineItem] of params.lineItems.entries()) {
80
+ const className = (lineItem.variantId ? byVariant.get(lineItem.variantId) : null) ??
81
+ byEntity.get(lineItem.entityId) ??
82
+ defaultClass?.name ??
83
+ null;
84
+ const taxClass = className ? (byName.get(className) ?? defaultClass) : defaultClass;
85
+ const base = Math.max(0, lineValues[i] - prorated[i]);
86
+ const taxAmount = taxClass
87
+ ? Math.max(0, Math.round((base * taxClass.rateBps) / 10_000))
88
+ : 0;
89
+ amountToCollect += taxAmount;
90
+ taxableAmount += base;
91
+ lines.push({ id: lineItem.id, taxClass: taxClass?.name ?? null, taxAmount });
92
+ if (taxClass) {
93
+ const entry = breakdown[taxClass.name] ?? {
94
+ rateBps: taxClass.rateBps,
95
+ amount: 0,
96
+ };
97
+ entry.amount += taxAmount;
98
+ breakdown[taxClass.name] = entry;
99
+ }
100
+ }
101
+ return {
102
+ amountToCollect,
103
+ taxableAmount,
104
+ rate: taxableAmount > 0 ? amountToCollect / taxableAmount : 0,
105
+ breakdown,
106
+ lines,
107
+ };
108
+ }
109
+ // ── Tax class management (issue #57) ─────────────────────────────────────
110
+ async createTaxClass(input, actor, ctx) {
111
+ const repo = this.requireRepository();
112
+ if (!repo.ok)
113
+ return repo;
114
+ if (input.rateBps < 0) {
115
+ return Err(new CommerceValidationError("rateBps must be non-negative."));
116
+ }
117
+ const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
118
+ if (input.isDefault)
119
+ await repo.value.clearDefaultClass(orgId, ctx);
120
+ const created = await repo.value.createClass({
121
+ organizationId: orgId,
122
+ name: input.name,
123
+ rateBps: input.rateBps,
124
+ isDefault: input.isDefault ?? false,
125
+ isActive: input.isActive ?? true,
126
+ }, ctx);
127
+ return Ok(created);
128
+ }
129
+ async listTaxClasses(actor, ctx) {
130
+ const repo = this.requireRepository();
131
+ if (!repo.ok)
132
+ return repo;
133
+ const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
134
+ return Ok(await repo.value.findAllClasses(orgId, ctx));
135
+ }
136
+ async updateTaxClass(id, patch, actor, ctx) {
137
+ const repo = this.requireRepository();
138
+ if (!repo.ok)
139
+ return repo;
140
+ const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
141
+ const existing = await repo.value.findClassById(orgId, id, ctx);
142
+ if (!existing)
143
+ return Err(new CommerceNotFoundError("Tax class not found."));
144
+ if (patch.isDefault)
145
+ await repo.value.clearDefaultClass(orgId, ctx);
146
+ const updated = await repo.value.updateClass(id, {
147
+ ...(patch.name !== undefined ? { name: patch.name } : {}),
148
+ ...(patch.rateBps !== undefined ? { rateBps: patch.rateBps } : {}),
149
+ ...(patch.isDefault !== undefined ? { isDefault: patch.isDefault } : {}),
150
+ ...(patch.isActive !== undefined ? { isActive: patch.isActive } : {}),
151
+ }, ctx);
152
+ return Ok(updated);
153
+ }
154
+ async deleteTaxClass(id, actor, ctx) {
155
+ const repo = this.requireRepository();
156
+ if (!repo.ok)
157
+ return repo;
158
+ const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
159
+ const existing = await repo.value.findClassById(orgId, id, ctx);
160
+ if (!existing)
161
+ return Err(new CommerceNotFoundError("Tax class not found."));
162
+ await repo.value.deleteClass(id, ctx);
163
+ return Ok({ deleted: true });
164
+ }
165
+ async matchRuntimeRates(orgId, toAddress, ctx) {
166
+ const rates = await this.repository.findActive(orgId, ctx);
167
+ if (rates.length === 0)
168
+ return [];
169
+ const country = toAddress.country?.toUpperCase();
170
+ const state = toAddress.state?.toUpperCase();
171
+ const countryMatches = rates.filter((r) => r.country === "*" || r.country.toUpperCase() === country);
172
+ const stateMatches = countryMatches.filter((r) => r.state != null && state != null && r.state.toUpperCase() === state);
173
+ if (stateMatches.length > 0)
174
+ return stateMatches;
175
+ return countryMatches.filter((r) => r.state == null);
176
+ }
18
177
  async reportTransaction(params) {
19
178
  if (!this.adapter)
20
179
  return Ok({ transactionId: params.transactionId });
@@ -31,4 +190,70 @@ export class TaxService {
31
190
  }
32
191
  return Ok(this.adapter);
33
192
  }
193
+ // ── Runtime tax-rate management (issue #45) ────────────────────────────
194
+ requireRepository() {
195
+ if (!this.repository) {
196
+ return Err(new CommerceValidationError("Tax rate persistence is not available."));
197
+ }
198
+ return Ok(this.repository);
199
+ }
200
+ async createTaxRate(input, actor, ctx) {
201
+ const repo = this.requireRepository();
202
+ if (!repo.ok)
203
+ return repo;
204
+ if (input.rateBps < 0) {
205
+ return Err(new CommerceValidationError("rateBps must be non-negative."));
206
+ }
207
+ const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
208
+ const rate = await repo.value.create({
209
+ organizationId: orgId,
210
+ name: input.name,
211
+ country: input.country.toUpperCase(),
212
+ state: input.state?.toUpperCase() ?? null,
213
+ rateBps: input.rateBps,
214
+ appliesToShipping: input.appliesToShipping ?? true,
215
+ priority: input.priority ?? 100,
216
+ isActive: input.isActive ?? true,
217
+ }, ctx);
218
+ return Ok(rate);
219
+ }
220
+ async listTaxRates(actor, ctx) {
221
+ const repo = this.requireRepository();
222
+ if (!repo.ok)
223
+ return repo;
224
+ const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
225
+ return Ok(await repo.value.findAll(orgId, ctx));
226
+ }
227
+ async updateTaxRate(id, patch, actor, ctx) {
228
+ const repo = this.requireRepository();
229
+ if (!repo.ok)
230
+ return repo;
231
+ const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
232
+ const existing = await repo.value.findById(orgId, id, ctx);
233
+ if (!existing)
234
+ return Err(new CommerceNotFoundError("Tax rate not found."));
235
+ const updated = await repo.value.update(id, {
236
+ ...(patch.name !== undefined ? { name: patch.name } : {}),
237
+ ...(patch.country !== undefined ? { country: patch.country.toUpperCase() } : {}),
238
+ ...(patch.state !== undefined ? { state: patch.state?.toUpperCase() ?? null } : {}),
239
+ ...(patch.rateBps !== undefined ? { rateBps: patch.rateBps } : {}),
240
+ ...(patch.appliesToShipping !== undefined
241
+ ? { appliesToShipping: patch.appliesToShipping }
242
+ : {}),
243
+ ...(patch.priority !== undefined ? { priority: patch.priority } : {}),
244
+ ...(patch.isActive !== undefined ? { isActive: patch.isActive } : {}),
245
+ }, ctx);
246
+ return Ok(updated);
247
+ }
248
+ async deleteTaxRate(id, actor, ctx) {
249
+ const repo = this.requireRepository();
250
+ if (!repo.ok)
251
+ return repo;
252
+ const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
253
+ const existing = await repo.value.findById(orgId, id, ctx);
254
+ if (!existing)
255
+ return Err(new CommerceNotFoundError("Tax rate not found."));
256
+ await repo.value.delete(id, ctx);
257
+ return Ok({ deleted: true });
258
+ }
34
259
  }
@@ -179,6 +179,13 @@ export declare const KERNEL_ALL_MODULES: {
179
179
  dialect: "pg";
180
180
  }>;
181
181
  }, import("../index.js").AuditService, Record<string, unknown>>;
182
+ readonly settings: AppModule<{
183
+ storeSettings: typeof import("../modules/settings/schema.js").storeSettings;
184
+ }, import("../modules/settings/service.js").SettingsService, Record<string, never>>;
185
+ readonly documents: AppModule<{
186
+ invoiceSequences: typeof import("../modules/documents/schema.js").invoiceSequences;
187
+ orderDocuments: typeof import("../modules/documents/schema.js").orderDocuments;
188
+ }, import("../modules/documents/service.js").DocumentsService, Record<string, never>>;
182
189
  readonly webhooks: AppModule<{
183
190
  webhookEndpoints: import("drizzle-orm/pg-core").PgTableWithColumns<{
184
191
  name: "webhook_endpoints";
@@ -1701,10 +1708,16 @@ export declare const KERNEL_ALL_MODULES: {
1701
1708
  readonly search: AppModule<Record<string, never>, import("../modules/search/service.js").SearchService, {
1702
1709
  catalog: import("../modules/catalog/service.js").CatalogServiceImpl;
1703
1710
  }>;
1704
- readonly shipping: AppModule<Record<string, never>, import("../modules/shipping/service.js").ShippingService, {
1711
+ readonly shipping: AppModule<{
1712
+ shippingZones: typeof import("../modules/shipping/schema.js").shippingZones;
1713
+ shippingRates: typeof import("../modules/shipping/schema.js").shippingRates;
1714
+ }, import("../modules/shipping/service.js").ShippingService, {
1705
1715
  catalog: import("../modules/catalog/service.js").CatalogServiceImpl;
1706
1716
  }>;
1707
- readonly tax: AppModule<Record<string, never>, import("../modules/tax/service.js").TaxService, Record<string, never>>;
1717
+ readonly tax: AppModule<{
1718
+ taxRates: typeof import("../modules/tax/schema.js").taxRates;
1719
+ taxClasses: typeof import("../modules/tax/schema.js").taxClasses;
1720
+ }, import("../modules/tax/service.js").TaxService, Record<string, never>>;
1708
1721
  readonly payments: AppModule<Record<string, never>, import("../modules/payments/service.js").PaymentsService, Record<string, never>>;
1709
1722
  readonly analytics: AppModule<Record<string, never>, import("../modules/analytics/service.js").AnalyticsService, Record<string, never>>;
1710
1723
  };
@@ -1 +1 @@
1
- {"version":3,"file":"kernel-modules.d.ts","sourceRoot":"","sources":["../../src/runtime/kernel-modules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAoB3D,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkBrB,CAAC;AAEX,2FAA2F;AAC3F,wBAAgB,wBAAwB,IAAI,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAoBpE;AAED,wBAAgB,8BAA8B,IAAI,SAAS,MAAM,EAAE,CAElE"}
1
+ {"version":3,"file":"kernel-modules.d.ts","sourceRoot":"","sources":["../../src/runtime/kernel-modules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAsB3D,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoBrB,CAAC;AAEX,2FAA2F;AAC3F,wBAAgB,wBAAwB,IAAI,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAoBpE;AAED,wBAAgB,8BAA8B,IAAI,SAAS,MAAM,EAAE,CAElE"}
@@ -4,6 +4,7 @@ import { analyticsModule } from "../modules/analytics/module.js";
4
4
  import { cartModule } from "../modules/cart/module.js";
5
5
  import { catalogModule } from "../modules/catalog/module.js";
6
6
  import { customersModule } from "../modules/customers/index.js";
7
+ import { documentsModule } from "../modules/documents/module.js";
7
8
  import { fulfillmentModule } from "../modules/fulfillment/module.js";
8
9
  import { inventoryModule } from "../modules/inventory/module.js";
9
10
  import { mediaModule } from "../modules/media/index.js";
@@ -13,11 +14,14 @@ import { paymentsModule } from "../modules/payments/module.js";
13
14
  import { pricingModule } from "../modules/pricing/index.js";
14
15
  import { promotionsModule } from "../modules/promotions/module.js";
15
16
  import { searchModule } from "../modules/search/module.js";
17
+ import { settingsModule } from "../modules/settings/module.js";
16
18
  import { shippingModule } from "../modules/shipping/module.js";
17
19
  import { taxModule } from "../modules/tax/module.js";
18
20
  import { webhooksModule } from "../modules/webhooks/index.js";
19
21
  export const KERNEL_ALL_MODULES = {
20
22
  audit: auditModule,
23
+ settings: settingsModule,
24
+ documents: documentsModule,
21
25
  webhooks: webhooksModule,
22
26
  media: mediaModule,
23
27
  organization: organizationModule,
@@ -16,6 +16,8 @@ import { PromotionService } from "../modules/promotions/service.js";
16
16
  import { TaxService } from "../modules/tax/service.js";
17
17
  import { ShippingService } from "../modules/shipping/service.js";
18
18
  import { SearchService } from "../modules/search/service.js";
19
+ import { SettingsService } from "../modules/settings/service.js";
20
+ import { DocumentsService } from "../modules/documents/service.js";
19
21
  import type { AuditService } from "../modules/audit/service.js";
20
22
  import { OrganizationService } from "../modules/organization/service.js";
21
23
  import { createLogger } from "../utils/logger.js";
@@ -51,6 +53,8 @@ export interface Kernel {
51
53
  tax: TaxService;
52
54
  shipping: ShippingService;
53
55
  search: SearchService;
56
+ settings: SettingsService;
57
+ documents: DocumentsService;
54
58
  audit: AuditService;
55
59
  compensationFailures: CompensationFailuresRepository;
56
60
  email: CommerceConfig["email"];
@@ -59,7 +63,7 @@ export interface Kernel {
59
63
  pluginPermissions: PluginPermission[];
60
64
  logger: ReturnType<typeof createLogger>;
61
65
  }
62
- export declare const KERNEL_REQUIRED_SERVICE_KEYS: ["catalog", "inventory", "media", "cart", "orders", "payments", "fulfillment", "customers", "webhooks", "analytics", "pricing", "promotions", "tax", "shipping", "search", "audit", "compensationFailures"];
66
+ export declare const KERNEL_REQUIRED_SERVICE_KEYS: ["catalog", "inventory", "media", "cart", "orders", "payments", "fulfillment", "customers", "webhooks", "analytics", "pricing", "promotions", "tax", "shipping", "search", "settings", "documents", "audit", "compensationFailures"];
63
67
  export declare function assertKernelServicesReady(services: Partial<Kernel["services"]>): asserts services is Kernel["services"];
64
68
  export declare function assertSortedBefore(topo: readonly string[], a: string, b: string): void;
65
69
  //# sourceMappingURL=kernel-types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"kernel-types.d.ts","sourceRoot":"","sources":["../../src/runtime/kernel-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EACjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,8BAA8B,EAAE,MAAM,sCAAsC,CAAC;AAEtF,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,YAAY,CAAC;IACpB,QAAQ,EAAE,eAAe,CAAC;IAC1B,QAAQ,EAAE;QACR,OAAO,EAAE,kBAAkB,CAAC;QAC5B,SAAS,EAAE,gBAAgB,CAAC;QAC5B,KAAK,EAAE,YAAY,CAAC;QACpB,IAAI,EAAE,WAAW,CAAC;QAClB,MAAM,EAAE,YAAY,CAAC;QACrB,QAAQ,EAAE,eAAe,CAAC;QAC1B,WAAW,EAAE,kBAAkB,CAAC;QAChC,SAAS,EAAE,eAAe,CAAC;QAC3B,QAAQ,EAAE,cAAc,GAAG;YACzB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;SACjE,CAAC;QACF,SAAS,EAAE,gBAAgB,CAAC;QAC5B,OAAO,EAAE,cAAc,CAAC;QACxB,UAAU,EAAE,gBAAgB,CAAC;QAC7B,GAAG,EAAE,UAAU,CAAC;QAChB,QAAQ,EAAE,eAAe,CAAC;QAC1B,MAAM,EAAE,aAAa,CAAC;QACtB,KAAK,EAAE,YAAY,CAAC;QACpB,oBAAoB,EAAE,8BAA8B,CAAC;QACrD,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;QAC/B,YAAY,EAAE,mBAAmB,CAAC;KACnC,CAAC;IACF,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;IACtC,MAAM,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;CACzC;AAED,eAAO,MAAM,4BAA4B,6MAkBW,CAAC;AAErD,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,GACpC,OAAO,CAAC,QAAQ,IAAI,MAAM,CAAC,UAAU,CAAC,CAMxC;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,GACR,IAAI,CAWN"}
1
+ {"version":3,"file":"kernel-types.d.ts","sourceRoot":"","sources":["../../src/runtime/kernel-types.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,8 @@ export const KERNEL_REQUIRED_SERVICE_KEYS = [
14
14
  "tax",
15
15
  "shipping",
16
16
  "search",
17
+ "settings",
18
+ "documents",
17
19
  "audit",
18
20
  "compensationFailures",
19
21
  ];
@@ -281,7 +281,7 @@ export async function createServer(config) {
281
281
  // body-limit stack apply (all are scoped to /api/*).
282
282
  app.route("/api/me", createCustomerPortalRoutes(kernel));
283
283
  if (config.routes) {
284
- config.routes(app, kernel);
284
+ config.routes(app, kernel, auth);
285
285
  }
286
286
  // OpenAPI spec — disabled in production unless explicitly enabled
287
287
  const exposeSpec = config.exposeOpenApiSpec ?? !isProd;
@@ -21,6 +21,7 @@ import type { PgDatabase, PgQueryResultHKT } from "drizzle-orm/pg-core";
21
21
  import type { CommerceConfig, CommercePlugin } from "../config/types.js";
22
22
  import type { Actor } from "../auth/types.js";
23
23
  import type { Kernel } from "../runtime/kernel.js";
24
+ import { type AuthInstance } from "../auth/setup.js";
24
25
  /**
25
26
  * Hono environment type for the test app. Declares the `actor` context
26
27
  * variable so c.set("actor", ...) / c.get("actor") are properly typed
@@ -38,6 +39,8 @@ export interface PluginTestApp {
38
39
  kernel: Kernel;
39
40
  /** Drizzle database instance for direct queries in test assertions. */
40
41
  db: PgDatabase<PgQueryResultHKT, Record<string, unknown>>;
42
+ /** The Better Auth instance passed to plugin routes (mint/verify API keys in tests). */
43
+ auth: AuthInstance;
41
44
  }
42
45
  /**
43
46
  * Creates a fully-wired test application for plugin E2E testing.
@@ -1 +1 @@
1
- {"version":3,"file":"create-plugin-test-app.d.ts","sourceRoot":"","sources":["../../src/test-utils/create-plugin-test-app.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAG9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAgBnD;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,EAAE;QACT,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;KACrB,CAAC;CACH,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,wFAAwF;IACxF,GAAG,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IAC7B,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,EAAE,EAAE,UAAU,CAAC,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC3D;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,cAAc,EACtB,eAAe,GAAE,OAAO,CAAC,cAAc,CAAM,GAC5C,OAAO,CAAC,aAAa,CAAC,CAgFxB"}
1
+ {"version":3,"file":"create-plugin-test-app.d.ts","sourceRoot":"","sources":["../../src/test-utils/create-plugin-test-app.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAG9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAKnD,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAajE;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,EAAE;QACT,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;KACrB,CAAC;CACH,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,wFAAwF;IACxF,GAAG,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IAC7B,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,EAAE,EAAE,UAAU,CAAC,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1D,wFAAwF;IACxF,IAAI,EAAE,YAAY,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,cAAc,EACtB,eAAe,GAAE,OAAO,CAAC,cAAc,CAAM,GAC5C,OAAO,CAAC,aAAa,CAAC,CAyFxB"}
@@ -24,6 +24,8 @@ import { buildSchema } from "../kernel/database/migrate.js";
24
24
  import { unwrapDb } from "../kernel/database/adapter.js";
25
25
  import { ensureDefaultOrg } from "../auth/org.js";
26
26
  import { mapErrorToStatus } from "../kernel/error-mapper.js";
27
+ import { createAuth } from "../auth/setup.js";
28
+ import { authMiddleware } from "../auth/middleware.js";
27
29
  // drizzle-kit/api uses CJS internally; createRequire provides ESM compat.
28
30
  const require = createRequire(import.meta.url);
29
31
  /**
@@ -56,7 +58,10 @@ export async function createPluginTestApp(plugin, configOverrides = {}) {
56
58
  // 5. Create OpenAPIHono --- matching production server.ts
57
59
  // Plugin routes register via manifest.ts which calls app.openapi().
58
60
  const app = new OpenAPIHono();
59
- // 6. Test actor middleware: parse x-test-actor header -> set on context
61
+ const auth = createAuth(kernel.database, config);
62
+ // 6. Test actor middleware: parse x-test-actor header -> set on context.
63
+ // Requests without the header fall through to the real auth middleware,
64
+ // so API keys minted by plugins (issue #51) authenticate like production.
60
65
  app.use("*", async (c, next) => {
61
66
  const header = c.req.header("x-test-actor");
62
67
  if (header) {
@@ -67,9 +72,15 @@ export async function createPluginTestApp(plugin, configOverrides = {}) {
67
72
  }
68
73
  await next();
69
74
  });
70
- // 7. Register plugin routes (deferred via config.routes)
75
+ app.use("*", async (c, next) => {
76
+ if (c.get("actor"))
77
+ return next();
78
+ return authMiddleware(auth, config)(c, next);
79
+ });
80
+ // 7. Register plugin routes (deferred via config.routes) — with the auth
81
+ // instance, matching server.ts's config.routes(app, kernel, auth).
71
82
  const routes = config.routes;
72
- routes?.(app, kernel);
83
+ routes?.(app, kernel, auth);
73
84
  // 8. Error handler matching production server.ts — maps CommerceError
74
85
  // subclasses (CommerceForbiddenError, CommerceNotFoundError, etc.)
75
86
  // to their proper HTTP status codes (403, 404, 409, 422, 503).
@@ -89,5 +100,6 @@ export async function createPluginTestApp(plugin, configOverrides = {}) {
89
100
  app,
90
101
  kernel,
91
102
  db: kernel.database.db,
103
+ auth,
92
104
  };
93
105
  }
@@ -1 +1 @@
1
- {"version":3,"file":"create-test-config.d.ts","sourceRoot":"","sources":["../../src/test-utils/create-test-config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAgDzD,wBAAsB,gBAAgB,CACpC,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GACtC,OAAO,CAAC,cAAc,CAAC,CA+GzB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,sBAAsB,CAC1C,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GACtC,OAAO,CAAC;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CAUnE"}
1
+ {"version":3,"file":"create-test-config.d.ts","sourceRoot":"","sources":["../../src/test-utils/create-test-config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAgDzD,wBAAsB,gBAAgB,CACpC,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GACtC,OAAO,CAAC,cAAc,CAAC,CAiHzB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,sBAAsB,CAC1C,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GACtC,OAAO,CAAC;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CAUnE"}
@@ -53,6 +53,7 @@ export async function createTestConfig(overrides = {}) {
53
53
  provider: "postgresql",
54
54
  },
55
55
  auth: {
56
+ allowTestActor: true,
56
57
  defaultOrganizationId: "org_default",
57
58
  requireEmailVerification: false,
58
59
  apiKeys: { enabled: true, defaultPermissions: ["catalog:read"] },
@@ -70,6 +71,7 @@ export async function createTestConfig(overrides = {}) {
70
71
  "orders:create",
71
72
  "orders:read",
72
73
  "orders:update",
74
+ "orders:manage",
73
75
  "cart:create",
74
76
  "cart:update",
75
77
  "customers:update:self",
@@ -0,0 +1,12 @@
1
+ import type { Kernel } from "../runtime/kernel.js";
2
+ /**
3
+ * Mark an order as paid (captured) for tests.
4
+ *
5
+ * Refund and return flows require a paid order — a refund moves collected money,
6
+ * and the order primitive rejects refunds on unpaid/pending orders. There is no
7
+ * public "set captured amount" service (capture() needs a live payment intent),
8
+ * so tests set the column here through a single typed helper rather than
9
+ * scattering raw SQL / `as any` casts across test files.
10
+ */
11
+ export declare function markOrderPaidForTest(kernel: Kernel, orderId: string, amountCaptured: number, paymentIntentId?: string): Promise<void>;
12
+ //# sourceMappingURL=order-test-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"order-test-helpers.d.ts","sourceRoot":"","sources":["../../src/test-utils/order-test-helpers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAGnD;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,EACtB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,IAAI,CAAC,CAMf"}
@@ -0,0 +1,18 @@
1
+ import { eq } from "drizzle-orm";
2
+ import { orders } from "../modules/orders/schema.js";
3
+ /**
4
+ * Mark an order as paid (captured) for tests.
5
+ *
6
+ * Refund and return flows require a paid order — a refund moves collected money,
7
+ * and the order primitive rejects refunds on unpaid/pending orders. There is no
8
+ * public "set captured amount" service (capture() needs a live payment intent),
9
+ * so tests set the column here through a single typed helper rather than
10
+ * scattering raw SQL / `as any` casts across test files.
11
+ */
12
+ export async function markOrderPaidForTest(kernel, orderId, amountCaptured, paymentIntentId) {
13
+ const db = kernel.database.db;
14
+ await db
15
+ .update(orders)
16
+ .set({ amountCaptured, ...(paymentIntentId ? { paymentIntentId } : {}) })
17
+ .where(eq(orders.id, orderId));
18
+ }
@@ -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,KA6BvB,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;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,KAoCvB,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"}
@@ -130,12 +130,19 @@ export const testActor = {
130
130
  "orders:create",
131
131
  "orders:read",
132
132
  "orders:update",
133
+ "orders:manage",
133
134
  "cart:create",
134
135
  "cart:update",
135
136
  "cart:read",
137
+ "cart:manage",
136
138
  "customers:update:self",
137
139
  "webhooks:manage",
138
140
  "pricing:manage",
141
+ "shipping:manage",
142
+ "tax:manage",
143
+ "settings:manage",
144
+ "analytics:read",
145
+ "staff:manage",
139
146
  "promotions:manage",
140
147
  "promotions:read",
141
148
  "audit:read",
@@ -28,7 +28,7 @@ export const testStaffActor = {
28
28
  role: "staff",
29
29
  permissions: [
30
30
  "catalog:read", "catalog:create", "catalog:update",
31
- "inventory:adjust", "orders:read", "orders:create", "orders:update",
31
+ "inventory:adjust", "orders:read", "orders:create", "orders:update", "orders:manage",
32
32
  ],
33
33
  };
34
34
  /** Customer with minimal read/write-own permissions. */
package/dist/testing.d.ts CHANGED
@@ -11,5 +11,6 @@ export { createRepositoryTestHarness } from "./test-utils/create-repository-test
11
11
  export { createPluginTestApp, type PluginTestApp, type TestAppEnv } from "./test-utils/create-plugin-test-app.js";
12
12
  export { TEST_ORG_ID, testAdminActor, testStaffActor, testCustomerActor, testNoPermActor, jsonHeaders, } from "./test-utils/test-actors.js";
13
13
  export { beforeHook, afterHook } from "./test-utils/typed-hooks.js";
14
+ export { markOrderPaidForTest } from "./test-utils/order-test-helpers.js";
14
15
  export type { Actor } from "./auth/types.js";
15
16
  //# sourceMappingURL=testing.d.ts.map
@@ -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;AACtE,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;AAGpE,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;AACtE,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;AAG1E,YAAY,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/testing.js CHANGED
@@ -11,3 +11,4 @@ export { createRepositoryTestHarness } from "./test-utils/create-repository-test
11
11
  export { createPluginTestApp } from "./test-utils/create-plugin-test-app.js";
12
12
  export { TEST_ORG_ID, testAdminActor, testStaffActor, testCustomerActor, testNoPermActor, jsonHeaders, } from "./test-utils/test-actors.js";
13
13
  export { beforeHook, afterHook } from "./test-utils/typed-hooks.js";
14
+ export { markOrderPaidForTest } from "./test-utils/order-test-helpers.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@porulle/core",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -56,8 +56,8 @@
56
56
  "eslint": "^9.39.1",
57
57
  "typescript": "5.9.2",
58
58
  "vitest": "^3.2.4",
59
- "@porulle/eslint-config": "0.1.0",
60
- "@porulle/typescript-config": "0.1.0"
59
+ "@porulle/typescript-config": "0.1.0",
60
+ "@porulle/eslint-config": "0.1.0"
61
61
  },
62
62
  "publishConfig": {
63
63
  "access": "public"