@classytic/loyalty 0.1.0 → 0.2.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/CHANGELOG.md +68 -0
- package/dist/config-JYTMP1F7.d.mts +136 -0
- package/dist/{constants-C75GvizO.mjs → constants-DkQYkOK1.mjs} +3 -2
- package/dist/domain/enums/index.d.mts +1 -1
- package/dist/domain/enums/index.mjs +1 -1
- package/dist/events/index.d.mts +2 -2
- package/dist/events/index.mjs +3 -3
- package/dist/events-BjzHSLBn.mjs +344 -0
- package/dist/index-2izQQext.d.mts +281 -0
- package/dist/index-BmqGuj38.d.mts +400 -0
- package/dist/{index-CaH4GhSF.d.mts → index-DMK8a98J.d.mts} +1 -1
- package/dist/index-qI1WvtNg.d.mts +361 -0
- package/dist/index.d.mts +28 -12
- package/dist/index.mjs +30 -26
- package/dist/loyalty-events-Cyt9TwX6.mjs +50 -0
- package/dist/models/index.d.mts +1225 -2
- package/dist/models/index.mjs +2 -2
- package/dist/{models-CrZPmVxt.mjs → models-uhh9c-7k.mjs} +104 -41
- package/dist/notifications/index.d.mts +1 -1
- package/dist/repositories/index.d.mts +2 -2
- package/dist/repositories/index.mjs +1 -1
- package/dist/repositories-ObGUgcSH.mjs +1917 -0
- package/dist/types/index.d.mts +2 -2
- package/package.json +18 -16
- package/dist/config-aNigy4ec.d.mts +0 -90
- package/dist/domain/index.d.mts +0 -90
- package/dist/domain/index.mjs +0 -4
- package/dist/domain-errors-D7q-2LYD.mjs +0 -120
- package/dist/event-emitter.port-CLYPoMni.d.mts +0 -8
- package/dist/event-types-xQBtYBbX.mjs +0 -24
- package/dist/events-CprEWlN7.mjs +0 -25
- package/dist/index-B6ZstxSP.d.mts +0 -2357
- package/dist/index-BcoGeDco.d.mts +0 -127
- package/dist/index-DqzTjeEB.d.mts +0 -148
- package/dist/index-O7TL4R2P.d.mts +0 -86
- package/dist/index-_pg4J11t.d.mts +0 -191
- package/dist/repositories-qMX7Xh_y.mjs +0 -440
- package/dist/services/index.d.mts +0 -2
- package/dist/services/index.mjs +0 -2
- package/dist/services-CoTqC4E6.mjs +0 -1098
- package/dist/tier-definition-Djf72UPa.d.mts +0 -120
- package/dist/tier-definition.port-BzrHYBRo.d.mts +0 -143
- /package/dist/{notification.port-BzUsH0It.d.mts → notification.port-9B5xlzxQ.d.mts} +0 -0
package/dist/models/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { createModels };
|
|
1
|
+
import { n as createModels, t as LoyaltyModelCollisionError } from "../models-uhh9c-7k.mjs";
|
|
2
|
+
export { LoyaltyModelCollisionError, createModels };
|
|
@@ -1,21 +1,44 @@
|
|
|
1
|
-
import { a as MEMBER_STATUSES, c as RULE_STATUSES, l as RULE_TYPES, o as REDEMPTION_STATUSES, s as REFERRAL_STATUSES, u as TRANSACTION_TYPES } from "./constants-
|
|
1
|
+
import { a as MEMBER_STATUSES, c as RULE_STATUSES, l as RULE_TYPES, o as REDEMPTION_STATUSES, s as REFERRAL_STATUSES, u as TRANSACTION_TYPES } from "./constants-DkQYkOK1.mjs";
|
|
2
2
|
import mongoose from "mongoose";
|
|
3
3
|
//#region src/models/create-model.ts
|
|
4
4
|
/**
|
|
5
|
-
* Injects the tenant field into a schema and
|
|
5
|
+
* Injects the tenant field into a schema and (when tenant scoping is enabled
|
|
6
|
+
* at the plugin layer) prepends it to ALL existing indexes.
|
|
7
|
+
*
|
|
8
|
+
* The field itself is added UNCONDITIONALLY — this mirrors the
|
|
9
|
+
* `@classytic/order` convention ("Child repos set `organizationId`
|
|
10
|
+
* explicitly on the doc. So writes work whether the host opts into the
|
|
11
|
+
* auto-wired `multiTenantPlugin` or sets `multiTenant: false` and enforces
|
|
12
|
+
* scoping at its own framework layer"). Arc hosts that scope via preset /
|
|
13
|
+
* `BaseController` need the schema field present so writes persist and
|
|
14
|
+
* filters match; turning off the mongokit plugin wouldn't help them if
|
|
15
|
+
* `organizationId` weren't a known schema path (Mongoose strict mode would
|
|
16
|
+
* strip it).
|
|
17
|
+
*
|
|
18
|
+
* `required: true` is intentionally NOT set — mongokit's
|
|
19
|
+
* `buildCrudSchemasFromModel` would forward it into arc's auto-generated
|
|
20
|
+
* request body JSON Schema and Fastify would reject valid POSTs at
|
|
21
|
+
* preValidation BEFORE arc's `BaseController.create` can inject orgId from
|
|
22
|
+
* scope. Enforcement comes from (a) arc's BaseController writing the field
|
|
23
|
+
* on every create/update and (b) mongokit's `multiTenantPlugin` (when
|
|
24
|
+
* enabled) throwing on missing ctx.
|
|
25
|
+
*
|
|
26
|
+
* Compound-index prefixing IS gated on `enabled`, since that concerns
|
|
27
|
+
* query efficiency and is only relevant when the mongokit-layer plugin
|
|
28
|
+
* scopes queries.
|
|
6
29
|
*/
|
|
7
30
|
function injectTenantField(schema, tenant) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
type: tenant.type === "ObjectId" ? mongoose.Schema.Types.ObjectId : String,
|
|
11
|
-
required: true,
|
|
31
|
+
schema.add({ [tenant.tenantField]: {
|
|
32
|
+
type: tenant.fieldType === "objectId" ? mongoose.Schema.Types.ObjectId : String,
|
|
12
33
|
index: true,
|
|
34
|
+
...tenant.enabled ? { required: true } : {},
|
|
13
35
|
...tenant.ref ? { ref: tenant.ref } : {}
|
|
14
36
|
} });
|
|
37
|
+
if (!tenant.enabled) return;
|
|
15
38
|
const existingIndexes = schema._indexes;
|
|
16
39
|
if (existingIndexes && existingIndexes.length > 0) for (const indexEntry of existingIndexes) {
|
|
17
40
|
const fields = indexEntry[0];
|
|
18
|
-
const newFields = { [tenant.
|
|
41
|
+
const newFields = { [tenant.tenantField]: 1 };
|
|
19
42
|
for (const [key, val] of Object.entries(fields)) newFields[key] = val;
|
|
20
43
|
indexEntry[0] = newFields;
|
|
21
44
|
}
|
|
@@ -26,7 +49,7 @@ function injectTenantField(schema, tenant) {
|
|
|
26
49
|
function applyUserIndexes(schema, indexes, tenant) {
|
|
27
50
|
for (const def of indexes) {
|
|
28
51
|
const fields = tenant.enabled ? {
|
|
29
|
-
[tenant.
|
|
52
|
+
[tenant.tenantField]: 1,
|
|
30
53
|
...def.fields
|
|
31
54
|
} : { ...def.fields };
|
|
32
55
|
schema.index(fields, def.options ?? {});
|
|
@@ -118,22 +141,16 @@ function createMemberSchema() {
|
|
|
118
141
|
enum: MEMBER_STATUSES,
|
|
119
142
|
default: "active"
|
|
120
143
|
},
|
|
121
|
-
cardId: {
|
|
122
|
-
|
|
123
|
-
unique: true,
|
|
124
|
-
sparse: true
|
|
125
|
-
},
|
|
126
|
-
referralCode: {
|
|
127
|
-
type: String,
|
|
128
|
-
unique: true,
|
|
129
|
-
sparse: true
|
|
130
|
-
},
|
|
144
|
+
cardId: { type: String },
|
|
145
|
+
referralCode: { type: String },
|
|
131
146
|
tier: {
|
|
132
147
|
type: String,
|
|
133
148
|
default: null
|
|
134
149
|
},
|
|
135
150
|
tierOverride: { type: String },
|
|
136
151
|
tierOverrideReason: { type: String },
|
|
152
|
+
tierOverrideExpiresAt: { type: Date },
|
|
153
|
+
referredBy: { type: String },
|
|
137
154
|
tierQualifiedAt: { type: Date },
|
|
138
155
|
tierExpiresAt: { type: Date },
|
|
139
156
|
balance: {
|
|
@@ -165,6 +182,14 @@ function createMemberSchema() {
|
|
|
165
182
|
externalId: 1,
|
|
166
183
|
externalType: 1
|
|
167
184
|
}, { unique: true });
|
|
185
|
+
schema.index({ cardId: 1 }, {
|
|
186
|
+
unique: true,
|
|
187
|
+
partialFilterExpression: { cardId: { $type: "string" } }
|
|
188
|
+
});
|
|
189
|
+
schema.index({ referralCode: 1 }, {
|
|
190
|
+
unique: true,
|
|
191
|
+
partialFilterExpression: { referralCode: { $type: "string" } }
|
|
192
|
+
});
|
|
168
193
|
return schema;
|
|
169
194
|
}
|
|
170
195
|
//#endregion
|
|
@@ -218,10 +243,7 @@ function createPointTransactionSchema() {
|
|
|
218
243
|
});
|
|
219
244
|
schema.index({ idempotencyKey: 1 }, {
|
|
220
245
|
unique: true,
|
|
221
|
-
partialFilterExpression: { idempotencyKey: {
|
|
222
|
-
$exists: true,
|
|
223
|
-
$ne: null
|
|
224
|
-
} }
|
|
246
|
+
partialFilterExpression: { idempotencyKey: { $type: "string" } }
|
|
225
247
|
});
|
|
226
248
|
return schema;
|
|
227
249
|
}
|
|
@@ -270,7 +292,12 @@ function createRedemptionSchema() {
|
|
|
270
292
|
expiresAt: { type: Date },
|
|
271
293
|
confirmedAt: { type: Date },
|
|
272
294
|
releasedAt: { type: Date },
|
|
273
|
-
|
|
295
|
+
reversedAt: { type: Date },
|
|
296
|
+
reversalReason: { type: String },
|
|
297
|
+
reversalTransactionId: { type: mongoose.Schema.Types.ObjectId },
|
|
298
|
+
transactionId: { type: mongoose.Schema.Types.ObjectId },
|
|
299
|
+
initialBalance: { type: Number },
|
|
300
|
+
remainingBalance: { type: Number }
|
|
274
301
|
}, { timestamps: true });
|
|
275
302
|
schema.index({
|
|
276
303
|
ownerType: 1,
|
|
@@ -374,21 +401,52 @@ function createTierDefinitionSchema() {
|
|
|
374
401
|
}
|
|
375
402
|
//#endregion
|
|
376
403
|
//#region src/models/index.ts
|
|
377
|
-
function
|
|
404
|
+
function applyAutoIndex(models, autoIndex) {
|
|
405
|
+
if (autoIndex === void 0) return;
|
|
406
|
+
for (const [name, model] of Object.entries(models)) {
|
|
407
|
+
const value = typeof autoIndex === "boolean" ? autoIndex : autoIndex[name] ?? void 0;
|
|
408
|
+
if (value !== void 0) model.schema.set("autoIndex", value);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Default physical collection names (see PACKAGE_RULES.md §20.1). Prefixed
|
|
413
|
+
* when `collectionPrefix` is provided; used verbatim when unset.
|
|
414
|
+
*/
|
|
415
|
+
const DEFAULT_COLLECTIONS = {
|
|
416
|
+
Member: "loyalty_members",
|
|
417
|
+
PointTransaction: "loyalty_point_transactions",
|
|
418
|
+
EarningRule: "loyalty_earning_rules",
|
|
419
|
+
TierDefinition: "loyalty_tier_definitions",
|
|
420
|
+
Redemption: "loyalty_redemptions",
|
|
421
|
+
Referral: "loyalty_referrals"
|
|
422
|
+
};
|
|
423
|
+
const LOYALTY_MODEL_NAMES = [
|
|
424
|
+
"LoyaltyMember",
|
|
425
|
+
"LoyaltyPointTransaction",
|
|
426
|
+
"LoyaltyEarningRule",
|
|
427
|
+
"LoyaltyTierDefinition",
|
|
428
|
+
"LoyaltyRedemption",
|
|
429
|
+
"LoyaltyReferral"
|
|
430
|
+
];
|
|
431
|
+
var LoyaltyModelCollisionError = class extends Error {
|
|
432
|
+
constructor(name) {
|
|
433
|
+
super(`[loyalty] Mongoose model "${name}" already exists on this connection. For hot-reload / test fixtures, pass \`forceRecreate: true\` to clobber the existing model. For two loyalty engines, use two Mongoose connections (\`mongoose.createConnection(...)\`) — each has its own model registry.`);
|
|
434
|
+
this.name = "LoyaltyModelCollisionError";
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
function createModels(connection, tenant, indexes, autoIndex, collectionPrefix, forceRecreate) {
|
|
378
438
|
const memberSchema = createMemberSchema();
|
|
379
439
|
const pointTransactionSchema = createPointTransactionSchema();
|
|
380
440
|
const earningRuleSchema = createEarningRuleSchema();
|
|
381
441
|
const tierDefinitionSchema = createTierDefinitionSchema();
|
|
382
442
|
const redemptionSchema = createRedemptionSchema();
|
|
383
443
|
const referralSchema = createReferralSchema();
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
injectTenantField(referralSchema, tenant);
|
|
391
|
-
}
|
|
444
|
+
injectTenantField(memberSchema, tenant);
|
|
445
|
+
injectTenantField(pointTransactionSchema, tenant);
|
|
446
|
+
injectTenantField(earningRuleSchema, tenant);
|
|
447
|
+
injectTenantField(tierDefinitionSchema, tenant);
|
|
448
|
+
injectTenantField(redemptionSchema, tenant);
|
|
449
|
+
injectTenantField(referralSchema, tenant);
|
|
392
450
|
if (indexes) {
|
|
393
451
|
const schemaMap = {
|
|
394
452
|
member: memberSchema,
|
|
@@ -403,15 +461,20 @@ function createModels(connection, tenant, indexes) {
|
|
|
403
461
|
if (schema && defs) applyUserIndexes(schema, defs, tenant);
|
|
404
462
|
}
|
|
405
463
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
464
|
+
if (forceRecreate) {
|
|
465
|
+
for (const name of LOYALTY_MODEL_NAMES) if (connection.models[name]) connection.deleteModel(name);
|
|
466
|
+
} else for (const name of LOYALTY_MODEL_NAMES) if (connection.models[name]) throw new LoyaltyModelCollisionError(name);
|
|
467
|
+
const prefix = collectionPrefix ?? "";
|
|
468
|
+
const models = {
|
|
469
|
+
Member: connection.model("LoyaltyMember", memberSchema, prefix + DEFAULT_COLLECTIONS.Member),
|
|
470
|
+
PointTransaction: connection.model("LoyaltyPointTransaction", pointTransactionSchema, prefix + DEFAULT_COLLECTIONS.PointTransaction),
|
|
471
|
+
EarningRule: connection.model("LoyaltyEarningRule", earningRuleSchema, prefix + DEFAULT_COLLECTIONS.EarningRule),
|
|
472
|
+
TierDefinition: connection.model("LoyaltyTierDefinition", tierDefinitionSchema, prefix + DEFAULT_COLLECTIONS.TierDefinition),
|
|
473
|
+
Redemption: connection.model("LoyaltyRedemption", redemptionSchema, prefix + DEFAULT_COLLECTIONS.Redemption),
|
|
474
|
+
Referral: connection.model("LoyaltyReferral", referralSchema, prefix + DEFAULT_COLLECTIONS.Referral)
|
|
414
475
|
};
|
|
476
|
+
applyAutoIndex(models, autoIndex);
|
|
477
|
+
return models;
|
|
415
478
|
}
|
|
416
479
|
//#endregion
|
|
417
|
-
export { createModels as t };
|
|
480
|
+
export { createModels as n, LoyaltyModelCollisionError as t };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { EarningRuleRepository, LoyaltyRepositories, MemberRepository, PointTransactionRepository, RedemptionRepository, ReferralRepository, TierDefinitionRepository, createRepositories };
|
|
1
|
+
import { a as ReferralRepository, d as MemberRepository, i as TierDefinitionRepository, l as EarningRuleRepository, n as LoyaltyRepositories, r as createRepositories, s as RedemptionRepository, t as CreateRepositoriesInput, u as PointTransactionRepository } from "../index-qI1WvtNg.mjs";
|
|
2
|
+
export { CreateRepositoriesInput, EarningRuleRepository, LoyaltyRepositories, MemberRepository, PointTransactionRepository, RedemptionRepository, ReferralRepository, TierDefinitionRepository, createRepositories };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as PointTransactionRepository, i as RedemptionRepository, n as TierDefinitionRepository, o as MemberRepository, r as ReferralRepository, s as EarningRuleRepository, t as createRepositories } from "../repositories-
|
|
1
|
+
import { a as PointTransactionRepository, i as RedemptionRepository, n as TierDefinitionRepository, o as MemberRepository, r as ReferralRepository, s as EarningRuleRepository, t as createRepositories } from "../repositories-ObGUgcSH.mjs";
|
|
2
2
|
export { EarningRuleRepository, MemberRepository, PointTransactionRepository, RedemptionRepository, ReferralRepository, TierDefinitionRepository, createRepositories };
|