@classytic/loyalty 0.2.3 → 0.4.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.
package/dist/index.mjs CHANGED
@@ -1,8 +1,10 @@
1
1
  import { n as DEFAULT_TENANT_FIELD, r as DEFAULT_TENANT_TYPE } from "./constants-DkQYkOK1.mjs";
2
- import { a as PointTransactionRepository, c as ValidationError, i as RedemptionRepository, n as TierDefinitionRepository, o as MemberRepository, r as ReferralRepository, s as EarningRuleRepository, t as createRepositories } from "./repositories-BMwidCp-.mjs";
3
- import { E as InProcessLoyaltyBus, T as loyaltyEventDefinitions, _ as ReferralRecorded, a as MemberSuspended, b as TierDowngraded, c as PointsEarned, d as PointsRedeemed, f as RedemptionConfirmed, g as ReferralApproved, i as MemberReactivated, l as PointsExpired, m as RedemptionReserved, n as MemberDeactivated, p as RedemptionReleased, r as MemberEnrolled, s as PointsAdjusted, u as PointsExpiringSoon, v as ReferralRejected, w as TierUpgraded, x as TierGraceStarted, y as ReferralRewarded } from "./events-BtZOdiPw.mjs";
4
- import { n as createModels } from "./models-0_OQIqBy.mjs";
5
- import { n as createEvent, t as LoyaltyEvents } from "./loyalty-events-Cyt9TwX6.mjs";
2
+ import { C as TenantIsolationError, E as ValidationError, S as SelfReferralError, T as UnmanagedSessionError, _ as RedemptionExpiredError, a as PointTransactionRepository, b as ReferralNotFoundError, c as flushPendingLoyaltyEvents, d as DuplicateReferralError, f as InsufficientPointsError, g as MemberNotFoundError, h as MemberInactiveError, i as RedemptionRepository, l as EarningRuleRepository, m as MemberAlreadyEnrolledError, n as TierDefinitionRepository, o as MemberRepository, p as LoyaltyCapabilityError, r as ReferralRepository, s as PENDING_EVENTS, t as createRepositories, u as CircularReferralError, v as RedemptionNotFoundError, w as TierNotFoundError, x as RuleNotFoundError, y as ReferralLimitExceededError } from "./repositories-DEwCbLCh.mjs";
3
+ import { E as InProcessLoyaltyBus, T as loyaltyEventDefinitions, _ as ReferralRecorded, a as MemberSuspended, b as TierDowngraded, c as PointsEarned, d as PointsRedeemed, f as RedemptionConfirmed, g as ReferralApproved, i as MemberReactivated, l as PointsExpired, m as RedemptionReserved, n as MemberDeactivated, p as RedemptionReleased, r as MemberEnrolled, s as PointsAdjusted, u as PointsExpiringSoon, v as ReferralRejected, w as TierUpgraded, x as TierGraceStarted, y as ReferralRewarded } from "./events-DN5_p6T0.mjs";
4
+ import { n as createModels } from "./models-Ddh62lgO.mjs";
5
+ import { n as createEvent, t as LoyaltyEvents } from "./loyalty-events-C38JA3cU.mjs";
6
+ import { withTransaction } from "@classytic/mongokit";
7
+ import { isValidTimeZone } from "@classytic/primitives/timezone";
6
8
  //#region src/index.ts
7
9
  function resolveConfig(config) {
8
10
  let tenant;
@@ -48,49 +50,47 @@ function resolveConfig(config) {
48
50
  enabled: config.expiry?.enabled ?? false,
49
51
  ...config.expiry?.defaultDays !== void 0 ? { defaultDays: config.expiry.defaultDays } : {}
50
52
  },
53
+ ...config.timezone !== void 0 ? { timezone: config.timezone } : {},
51
54
  tenant
52
55
  };
56
+ if (config.timezone !== void 0 && !isValidTimeZone(config.timezone)) throw new ValidationError(`Invalid IANA timezone: '${config.timezone}'`);
53
57
  if (resolved.conversionRate <= 0) throw new ValidationError("conversionRate must be positive");
54
58
  if (resolved.referral.codeLength < 4) throw new ValidationError("referral codeLength must be >= 4");
55
59
  if (resolved.redemption.maxRedeemPercent < 0 || resolved.redemption.maxRedeemPercent > 100) throw new ValidationError("maxRedeemPercent must be between 0 and 100");
56
60
  return resolved;
57
61
  }
58
62
  var MongoUnitOfWork = class {
59
- constructor(connection) {
63
+ constructor(connection, allowFallback) {
60
64
  this.connection = connection;
65
+ this.allowFallback = allowFallback;
61
66
  }
62
67
  async withTransaction(cb) {
63
- const session = await this.connection.startSession();
64
- try {
65
- const slot = { assigned: false };
66
- await session.withTransaction(async () => {
67
- slot.value = await cb(session);
68
- slot.assigned = true;
69
- });
70
- if (!slot.assigned) throw new Error("withTransaction: callback did not assign a result");
71
- return slot.value;
72
- } finally {
73
- await session.endSession();
74
- }
68
+ return withTransaction(this.connection, cb, this.allowFallback ? { allowFallback: true } : {});
75
69
  }
76
70
  };
77
71
  function createLoyaltyEngine(config) {
78
72
  const resolvedConfig = resolveConfig(config);
79
73
  const models = createModels(config.mongoose, resolvedConfig.tenant, config.indexes, config.autoIndex, config.collectionPrefix, config.forceRecreate);
80
- const unitOfWork = new MongoUnitOfWork(config.mongoose);
74
+ const unitOfWork = new MongoUnitOfWork(config.mongoose, config.allowNonTransactional ?? false);
81
75
  const events = config.eventTransport ?? new InProcessLoyaltyBus();
76
+ const repositories = createRepositories({
77
+ models,
78
+ plugins: config.plugins,
79
+ tenant: resolvedConfig.tenant,
80
+ config: resolvedConfig,
81
+ events,
82
+ outbox: config.outbox,
83
+ notifications: config.notifications ?? null,
84
+ unitOfWork
85
+ });
86
+ if (!config.allowNonTransactional) {
87
+ const caps = repositories.pointTransaction.capabilities;
88
+ if (!caps) throw new LoyaltyCapabilityError(["capabilities descriptor (repo-core 0.6 / mongokit 3.16+) — backend declares none"]);
89
+ if (caps.transactions !== true) throw new LoyaltyCapabilityError(["transactions"]);
90
+ }
82
91
  return {
83
92
  models,
84
- repositories: createRepositories({
85
- models,
86
- plugins: config.plugins,
87
- tenant: resolvedConfig.tenant,
88
- config: resolvedConfig,
89
- events,
90
- outbox: config.outbox,
91
- notifications: config.notifications ?? null,
92
- unitOfWork
93
- }),
93
+ repositories,
94
94
  events,
95
95
  async syncIndexes() {
96
96
  await Promise.all(Object.values(models).map((m) => m.createIndexes()));
@@ -98,4 +98,4 @@ function createLoyaltyEngine(config) {
98
98
  };
99
99
  }
100
100
  //#endregion
101
- export { EarningRuleRepository, InProcessLoyaltyBus, LoyaltyEvents, MemberDeactivated, MemberEnrolled, MemberReactivated, MemberRepository, MemberSuspended, PointTransactionRepository, PointsAdjusted, PointsEarned, PointsExpired, PointsExpiringSoon, PointsRedeemed, RedemptionConfirmed, RedemptionReleased, RedemptionRepository, RedemptionReserved, ReferralApproved, ReferralRecorded, ReferralRejected, ReferralRepository, ReferralRewarded, TierDefinitionRepository, TierDowngraded, TierGraceStarted, TierUpgraded, createEvent, createLoyaltyEngine, loyaltyEventDefinitions, resolveConfig };
101
+ export { CircularReferralError, DuplicateReferralError, EarningRuleRepository, InProcessLoyaltyBus, InsufficientPointsError, LoyaltyCapabilityError, LoyaltyEvents, MemberAlreadyEnrolledError, MemberDeactivated, MemberEnrolled, MemberInactiveError, MemberNotFoundError, MemberReactivated, MemberRepository, MemberSuspended, PENDING_EVENTS, PointTransactionRepository, PointsAdjusted, PointsEarned, PointsExpired, PointsExpiringSoon, PointsRedeemed, RedemptionConfirmed, RedemptionExpiredError, RedemptionNotFoundError, RedemptionReleased, RedemptionRepository, RedemptionReserved, ReferralApproved, ReferralLimitExceededError, ReferralNotFoundError, ReferralRecorded, ReferralRejected, ReferralRepository, ReferralRewarded, RuleNotFoundError, SelfReferralError, TenantIsolationError, TierDefinitionRepository, TierDowngraded, TierGraceStarted, TierNotFoundError, TierUpgraded, UnmanagedSessionError, ValidationError, createEvent, createLoyaltyEngine, flushPendingLoyaltyEvents, loyaltyEventDefinitions, resolveConfig };
@@ -1,9 +1,11 @@
1
1
  import { createEvent } from "@classytic/primitives/events";
2
2
  //#region src/events/helpers.ts
3
3
  function createEvent$1(type, payload, ctx, meta) {
4
+ const base = {};
5
+ if (ctx?.actorId !== void 0) base.userId = ctx.actorId;
6
+ if (ctx?.organizationId !== void 0) base.organizationId = ctx.organizationId;
4
7
  return createEvent(type, payload, {
5
- userId: ctx?.actorId,
6
- organizationId: ctx?.organizationId,
8
+ ...base,
7
9
  ...meta
8
10
  });
9
11
  }