@porulle/core 0.8.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 (85) 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 +7 -5
  5. package/dist/config/defaults.d.ts.map +1 -1
  6. package/dist/config/defaults.js +2 -0
  7. package/dist/config/types.d.ts +9 -0
  8. package/dist/config/types.d.ts.map +1 -1
  9. package/dist/hooks/checkout-completion.d.ts.map +1 -1
  10. package/dist/hooks/checkout-completion.js +2 -2
  11. package/dist/hooks/checkout.d.ts.map +1 -1
  12. package/dist/hooks/checkout.js +1 -1
  13. package/dist/interfaces/rest/routes/admin/staff.d.ts.map +1 -1
  14. package/dist/interfaces/rest/routes/admin/staff.js +37 -3
  15. package/dist/interfaces/rest/routes/checkout.d.ts +9 -0
  16. package/dist/interfaces/rest/routes/checkout.d.ts.map +1 -1
  17. package/dist/interfaces/rest/routes/checkout.js +81 -22
  18. package/dist/interfaces/rest/routes/inventory.d.ts.map +1 -1
  19. package/dist/interfaces/rest/routes/inventory.js +13 -0
  20. package/dist/interfaces/rest/routes/orders.d.ts.map +1 -1
  21. package/dist/interfaces/rest/routes/orders.js +13 -0
  22. package/dist/interfaces/rest/schemas/orders.js +2 -2
  23. package/dist/interfaces/rest/schemas/responses.d.ts +34 -0
  24. package/dist/interfaces/rest/schemas/responses.d.ts.map +1 -1
  25. package/dist/kernel/database/scoped-db.d.ts +2 -1
  26. package/dist/kernel/database/scoped-db.d.ts.map +1 -1
  27. package/dist/kernel/database/scoped-db.js +62 -1
  28. package/dist/kernel/plugin/manifest.d.ts +3 -0
  29. package/dist/kernel/plugin/manifest.d.ts.map +1 -1
  30. package/dist/modules/analytics/drizzle-adapter.d.ts.map +1 -1
  31. package/dist/modules/analytics/drizzle-adapter.js +16 -3
  32. package/dist/modules/cart/service.d.ts.map +1 -1
  33. package/dist/modules/cart/service.js +3 -2
  34. package/dist/modules/catalog/entity-service.d.ts.map +1 -1
  35. package/dist/modules/catalog/entity-service.js +34 -2
  36. package/dist/modules/customers/service.d.ts.map +1 -1
  37. package/dist/modules/customers/service.js +6 -0
  38. package/dist/modules/orders/schema.d.ts +17 -0
  39. package/dist/modules/orders/schema.d.ts.map +1 -1
  40. package/dist/modules/orders/schema.js +4 -0
  41. package/dist/modules/orders/service.d.ts +16 -2
  42. package/dist/modules/orders/service.d.ts.map +1 -1
  43. package/dist/modules/orders/service.js +223 -26
  44. package/dist/modules/orders/stale-order-cleanup.d.ts.map +1 -1
  45. package/dist/modules/orders/stale-order-cleanup.js +13 -1
  46. package/dist/modules/pricing/service.d.ts.map +1 -1
  47. package/dist/modules/pricing/service.js +5 -5
  48. package/dist/test-utils/create-test-config.d.ts.map +1 -1
  49. package/dist/test-utils/create-test-config.js +2 -0
  50. package/dist/test-utils/order-test-helpers.d.ts +12 -0
  51. package/dist/test-utils/order-test-helpers.d.ts.map +1 -0
  52. package/dist/test-utils/order-test-helpers.js +18 -0
  53. package/dist/test-utils/rest-api-test-utils.d.ts.map +1 -1
  54. package/dist/test-utils/rest-api-test-utils.js +1 -0
  55. package/dist/test-utils/test-actors.js +1 -1
  56. package/dist/testing.d.ts +1 -0
  57. package/dist/testing.d.ts.map +1 -1
  58. package/dist/testing.js +1 -0
  59. package/package.json +1 -1
  60. package/src/auth/middleware.ts +26 -7
  61. package/src/auth/setup.ts +10 -4
  62. package/src/config/defaults.ts +2 -0
  63. package/src/config/types.ts +9 -0
  64. package/src/hooks/checkout-completion.ts +22 -16
  65. package/src/hooks/checkout.ts +11 -8
  66. package/src/interfaces/rest/routes/admin/staff.ts +45 -3
  67. package/src/interfaces/rest/routes/checkout.ts +93 -28
  68. package/src/interfaces/rest/routes/inventory.ts +14 -0
  69. package/src/interfaces/rest/routes/orders.ts +11 -0
  70. package/src/interfaces/rest/schemas/orders.ts +2 -2
  71. package/src/kernel/database/scoped-db.ts +70 -1
  72. package/src/kernel/plugin/manifest.ts +3 -0
  73. package/src/modules/analytics/drizzle-adapter.ts +19 -3
  74. package/src/modules/cart/service.ts +3 -2
  75. package/src/modules/catalog/entity-service.ts +28 -1
  76. package/src/modules/customers/service.ts +6 -0
  77. package/src/modules/orders/schema.ts +4 -0
  78. package/src/modules/orders/service.ts +408 -64
  79. package/src/modules/orders/stale-order-cleanup.ts +18 -4
  80. package/src/modules/pricing/service.ts +5 -6
  81. package/src/test-utils/create-test-config.ts +2 -0
  82. package/src/test-utils/order-test-helpers.ts +26 -0
  83. package/src/test-utils/rest-api-test-utils.ts +1 -0
  84. package/src/test-utils/test-actors.ts +1 -1
  85. package/src/testing.ts +1 -0
@@ -271,7 +271,12 @@ export class EntityService {
271
271
  entity = refetched;
272
272
  }
273
273
  }
274
- if (actor && entity.organizationId && entity.organizationId !== resolveOrgId(actor)) return Err(new CommerceNotFoundError("Entity not found."));
274
+ const resolvedActor = actor ?? ctx?.actor ?? null;
275
+ try {
276
+ this.assertSameOrg(entity, resolvedActor);
277
+ } catch (error) {
278
+ return Err(toCommerceError(error));
279
+ }
275
280
  const result = await this.hydrateEntity(entity, processed.options ?? options, ctx);
276
281
  const entityAfterHooks = this.deps.hooks.resolve(`catalog.${entity.type}.afterRead`) as CatalogReadAfterHook[];
277
282
  const report = mergeHookReports(await runAfterHooks(globalAfterHooks, null, result, "read", context), await runAfterHooks(entityAfterHooks, null, result, "read", context));
@@ -407,6 +412,11 @@ export class EntityService {
407
412
  assertPermission(actor, "catalog:update");
408
413
  const entity = await this.repo.findEntityById(input.entityId, ctx);
409
414
  if (!entity) return Err(new CommerceNotFoundError("Entity not found."));
415
+ try {
416
+ this.assertSameOrg(entity, actor);
417
+ } catch (error) {
418
+ return Err(toCommerceError(error));
419
+ }
410
420
  const optionType = await this.repo.createOptionType({ entityId: input.entityId, name: input.name, displayName: input.name, sortOrder: 0 }, ctx);
411
421
  if (input.values) {
412
422
  for (const value of input.values) {
@@ -420,6 +430,13 @@ export class EntityService {
420
430
  assertPermission(actor, "catalog:update");
421
431
  const optionType = await this.repo.findOptionTypeById(input.optionTypeId, ctx);
422
432
  if (!optionType) return Err(new CommerceNotFoundError("Option type not found."));
433
+ const entity = await this.repo.findEntityById(optionType.entityId, ctx);
434
+ if (!entity) return Err(new CommerceNotFoundError("Entity not found."));
435
+ try {
436
+ this.assertSameOrg(entity, actor);
437
+ } catch (error) {
438
+ return Err(toCommerceError(error));
439
+ }
423
440
  return Ok(await this.repo.createOptionValue({ optionTypeId: input.optionTypeId, value: input.value, displayValue: input.value, sortOrder: 0, metadata: {} }, ctx));
424
441
  }
425
442
 
@@ -427,6 +444,11 @@ export class EntityService {
427
444
  assertPermission(actor, "catalog:update");
428
445
  const entity = await this.repo.findEntityById(input.entityId, ctx);
429
446
  if (!entity) return Err(new CommerceNotFoundError("Entity not found."));
447
+ try {
448
+ this.assertSameOrg(entity, actor);
449
+ } catch (error) {
450
+ return Err(toCommerceError(error));
451
+ }
430
452
  const entityOptionTypes = await this.repo.findOptionTypesByEntityId(input.entityId, ctx);
431
453
  const optionValueIds: string[] = [];
432
454
  for (const [optName, optVal] of Object.entries(input.options)) {
@@ -461,6 +483,11 @@ export class EntityService {
461
483
  }
462
484
  const entity = await this.repo.findEntityById(entityId, ctx);
463
485
  if (!entity) return Err(new CommerceNotFoundError("Entity not found."));
486
+ try {
487
+ this.assertSameOrg(entity, actor);
488
+ } catch (error) {
489
+ return Err(toCommerceError(error));
490
+ }
464
491
  const entityOptionTypes = await this.repo.findOptionTypesByEntityId(entityId, ctx);
465
492
  const sortedOptionTypes = entityOptionTypes.sort((a, b) => a.sortOrder - b.sortOrder);
466
493
  const optionValueGroups: string[][] = [];
@@ -241,6 +241,12 @@ export class CustomerService {
241
241
  ctx?: TxContext,
242
242
  options?: { replaceMetadata?: boolean },
243
243
  ): Promise<Result<Customer>> {
244
+ try {
245
+ assertPermission(actor ?? null, "customers:update");
246
+ } catch (error) {
247
+ return Err(toCommerceError(error));
248
+ }
249
+
244
250
  const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
245
251
  const existing = await this.repo.findById(orgId, id, ctx);
246
252
  if (!existing) return Err(new CommerceNotFoundError("Customer not found."));
@@ -50,6 +50,10 @@ export const orderLineItems = pgTable("order_line_items", {
50
50
  quantity: integer("quantity").notNull(),
51
51
  unitPrice: integer("unit_price").notNull(),
52
52
  totalPrice: integer("total_price").notNull(),
53
+ // Price provenance (matches Medusa's `is_custom_price`): true when a staff
54
+ // actor with `orders:manage` supplied an explicit override price rather than
55
+ // the server-derived catalog price. Audit + reporting signal.
56
+ isCustomPrice: boolean("is_custom_price").notNull().default(false),
53
57
  taxAmount: integer("tax_amount").notNull().default(0),
54
58
  discountAmount: integer("discount_amount").notNull().default(0),
55
59
  // Units already refunded on this line (issue #52) — line-level refund REST