@dappermountain/payload-plugin-achievements 0.2.1 → 0.2.2
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/README.md +12 -0
- package/dist/collections/Logs/index.d.ts.map +1 -1
- package/dist/collections/Logs/index.js +3 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/services/achievement/grantSideEffects.d.ts.map +1 -1
- package/dist/services/achievement/grantSideEffects.js +9 -8
- package/dist/services/achievement/index.d.ts +2 -0
- package/dist/services/achievement/index.d.ts.map +1 -1
- package/dist/services/achievement/index.js +1 -0
- package/dist/services/achievement/logData.d.ts +31 -0
- package/dist/services/achievement/logData.d.ts.map +1 -0
- package/dist/services/achievement/logData.js +30 -0
- package/dist/services/achievement/reconcile.d.ts.map +1 -1
- package/dist/services/achievement/reconcile.js +7 -4
- package/dist/services/achievement/recordEvent.d.ts.map +1 -1
- package/dist/services/achievement/recordEvent.js +20 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -279,6 +279,18 @@ await runReconcileCli({ config })
|
|
|
279
279
|
|
|
280
280
|
Pass catalog **slugs** (or ids) for `type` and `metric`. Metric totals are the sum of `change` on matching logs. Creating or deleting **grants** (Admin or API) writes `achievement.granted` / `achievement.revoked`, syncs composed achievements, and may open tier requests / write `tier.changed`.
|
|
281
281
|
|
|
282
|
+
Engine log `data` for those system events uses a shared transition envelope:
|
|
283
|
+
|
|
284
|
+
```ts
|
|
285
|
+
{ from: { id, slug? } | null, to: { id, slug? } | null }
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
| type | `from` | `to` |
|
|
289
|
+
| --- | --- | --- |
|
|
290
|
+
| `tier.changed` | previous tier (null on first climb) | current tier |
|
|
291
|
+
| `achievement.granted` | `null` | achievement |
|
|
292
|
+
| `achievement.revoked` | achievement | `null` |
|
|
293
|
+
|
|
282
294
|
Turning **Requires review** off on a definition or tier **approves pending requests** for that row only (each waiting user goes through the existing request hooks).
|
|
283
295
|
|
|
284
296
|
**Admin:** Grants list includes **Repair progression**, which `POST`s the reconcile endpoint (requires `canReview`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/collections/Logs/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAS,MAAM,SAAS,CAAA;AAUtD,+EAA+E;AAC/E,wBAAgB,mBAAmB,IAAI,gBAAgB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/collections/Logs/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAS,MAAM,SAAS,CAAA;AAUtD,+EAA+E;AAC/E,wBAAgB,mBAAmB,IAAI,gBAAgB,CA6GtD"}
|
|
@@ -104,7 +104,9 @@ export function buildLogsCollection() {
|
|
|
104
104
|
{
|
|
105
105
|
name: 'data',
|
|
106
106
|
type: 'json',
|
|
107
|
-
admin: {
|
|
107
|
+
admin: {
|
|
108
|
+
description: 'Engine transition envelope: `{ from, to }` each `{ id, slug? }` or null (tier.changed, achievement.granted/revoked). Hosts may add extra keys.',
|
|
109
|
+
},
|
|
108
110
|
},
|
|
109
111
|
],
|
|
110
112
|
},
|
package/dist/index.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ export type { EngineEventTypeSlug, EngineMetricSlug } from './catalog';
|
|
|
3
3
|
export { achievementPlugin } from './plugin';
|
|
4
4
|
export { seedAchievementCatalog, seedAchievements } from './seed/index';
|
|
5
5
|
export type { AchievementSeedAchievement, AchievementSeedCatalogRow, AchievementSeedInput, AchievementSeedLocalizedText, AchievementSeedTier, } from './seed/index';
|
|
6
|
-
export { evaluateRules, evaluateRuleProgress, collectAchievementCompleteRefs, buildCatalogProgressGroups, getUserProgress, grantAchievement, recordEvent, recordLog, recordMetricChange, reconcileProgression, reconcileUserProgression, releasePendingAchievementReviews, releasePendingTierReviews, resolveCurrentTier, resolveTierProgress, reviewAchievementRequest, submitAchievementRequest, syncTierChangedLog, syncTierProgression, syncCompositeProgression, validateRuleGroup, validateRuleNode, } from './services/achievement/index';
|
|
7
|
-
export type { ResolvedTier, RuleGroup, TierLadderProgress, CatalogProgressGroup, CatalogProgressItem, ReconcileProgressionArgs, ReconcileProgressionResult, ReleaseReviewGateResult, } from './services/achievement/index';
|
|
6
|
+
export { evaluateRules, evaluateRuleProgress, collectAchievementCompleteRefs, buildCatalogProgressGroups, getUserProgress, grantAchievement, recordEvent, recordLog, recordMetricChange, reconcileProgression, reconcileUserProgression, releasePendingAchievementReviews, releasePendingTierReviews, resolveCurrentTier, resolveTierProgress, reviewAchievementRequest, submitAchievementRequest, syncTierChangedLog, syncTierProgression, syncCompositeProgression, catalogRef, transitionLogData, transitionToId, validateRuleGroup, validateRuleNode, } from './services/achievement/index';
|
|
7
|
+
export type { ResolvedTier, RuleGroup, TierLadderProgress, CatalogProgressGroup, CatalogProgressItem, CatalogRef, TransitionLogData, ReconcileProgressionArgs, ReconcileProgressionResult, ReleaseReviewGateResult, } from './services/achievement/index';
|
|
8
8
|
export type { BuiltInEventType, BuiltInRuleType, AchievementCollectionKey, AchievementCollectionOverride, AchievementCollectionsOptions, AchievementEndpointsOptions, AchievementPluginOptions, AchievementRuleType, AchievementScopeConfig, AchievementUsersOptions, } from './types';
|
|
9
9
|
export { DEFAULT_COLLECTION_BASE_SLUGS, DEFAULT_COLLECTION_PREFIX, DEFAULT_ADMIN_GROUP } from './collections/slugs';
|
|
10
10
|
export { DEFAULT_ME_ENDPOINT_PATH, DEFAULT_RECONCILE_ENDPOINT_PATH } from './defaults';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,+BAA+B,EAC/B,kBAAkB,EAClB,cAAc,GACf,MAAM,WAAW,CAAA;AAClB,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACvE,YAAY,EACV,0BAA0B,EAC1B,yBAAyB,EACzB,oBAAoB,EACpB,4BAA4B,EAC5B,mBAAmB,GACpB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,8BAA8B,EAC9B,0BAA0B,EAC1B,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,SAAS,EACT,kBAAkB,EAClB,oBAAoB,EACpB,wBAAwB,EACxB,gCAAgC,EAChC,yBAAyB,EACzB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,wBAAwB,EACxB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,8BAA8B,CAAA;AACrC,YAAY,EACV,YAAY,EACZ,SAAS,EACT,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,wBAAwB,EACxB,0BAA0B,EAC1B,uBAAuB,GACxB,MAAM,8BAA8B,CAAA;AACrC,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,wBAAwB,EACxB,6BAA6B,EAC7B,6BAA6B,EAC7B,2BAA2B,EAC3B,wBAAwB,EACxB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,6BAA6B,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AACnH,OAAO,EAAE,wBAAwB,EAAE,+BAA+B,EAAE,MAAM,YAAY,CAAA;AACtF,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,+BAA+B,EAC/B,kBAAkB,EAClB,cAAc,GACf,MAAM,WAAW,CAAA;AAClB,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACvE,YAAY,EACV,0BAA0B,EAC1B,yBAAyB,EACzB,oBAAoB,EACpB,4BAA4B,EAC5B,mBAAmB,GACpB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,8BAA8B,EAC9B,0BAA0B,EAC1B,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,SAAS,EACT,kBAAkB,EAClB,oBAAoB,EACpB,wBAAwB,EACxB,gCAAgC,EAChC,yBAAyB,EACzB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,wBAAwB,EACxB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,8BAA8B,CAAA;AACrC,YAAY,EACV,YAAY,EACZ,SAAS,EACT,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,UAAU,EACV,iBAAiB,EACjB,wBAAwB,EACxB,0BAA0B,EAC1B,uBAAuB,GACxB,MAAM,8BAA8B,CAAA;AACrC,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,wBAAwB,EACxB,6BAA6B,EAC7B,6BAA6B,EAC7B,2BAA2B,EAC3B,wBAAwB,EACxB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,6BAA6B,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AACnH,OAAO,EAAE,wBAAwB,EAAE,+BAA+B,EAAE,MAAM,YAAY,CAAA;AACtF,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { DEFAULT_ACHIEVEMENT_METRIC, DEFAULT_ACHIEVEMENT_METRIC_SLUG, ENGINE_EVENT_TYPES, ENGINE_METRICS, } from './catalog';
|
|
2
2
|
export { achievementPlugin } from './plugin';
|
|
3
3
|
export { seedAchievementCatalog, seedAchievements } from './seed/index';
|
|
4
|
-
export { evaluateRules, evaluateRuleProgress, collectAchievementCompleteRefs, buildCatalogProgressGroups, getUserProgress, grantAchievement, recordEvent, recordLog, recordMetricChange, reconcileProgression, reconcileUserProgression, releasePendingAchievementReviews, releasePendingTierReviews, resolveCurrentTier, resolveTierProgress, reviewAchievementRequest, submitAchievementRequest, syncTierChangedLog, syncTierProgression, syncCompositeProgression, validateRuleGroup, validateRuleNode, } from './services/achievement/index';
|
|
4
|
+
export { evaluateRules, evaluateRuleProgress, collectAchievementCompleteRefs, buildCatalogProgressGroups, getUserProgress, grantAchievement, recordEvent, recordLog, recordMetricChange, reconcileProgression, reconcileUserProgression, releasePendingAchievementReviews, releasePendingTierReviews, resolveCurrentTier, resolveTierProgress, reviewAchievementRequest, submitAchievementRequest, syncTierChangedLog, syncTierProgression, syncCompositeProgression, catalogRef, transitionLogData, transitionToId, validateRuleGroup, validateRuleNode, } from './services/achievement/index';
|
|
5
5
|
export { DEFAULT_COLLECTION_BASE_SLUGS, DEFAULT_COLLECTION_PREFIX, DEFAULT_ADMIN_GROUP } from './collections/slugs';
|
|
6
6
|
export { DEFAULT_ME_ENDPOINT_PATH, DEFAULT_RECONCILE_ENDPOINT_PATH } from './defaults';
|
|
7
7
|
export { collectionOf, slugOf } from './collections/helpers';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grantSideEffects.d.ts","sourceRoot":"","sources":["../../../src/services/achievement/grantSideEffects.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAS,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"grantSideEffects.d.ts","sourceRoot":"","sources":["../../../src/services/achievement/grantSideEffects.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAS,MAAM,SAAS,CAAA;AAWpD,OAAO,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAStG,wEAAwE;AACxE,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,GAAG,EAAE,cAAc,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA+BnC;AAED,6EAA6E;AAC7E,wBAAsB,wBAAwB,CAAC,IAAI,EAAE;IACnD,GAAG,EAAE,cAAc,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAuC9D;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAAC,IAAI,EAAE;IACnD,GAAG,EAAE,cAAc,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAsElD;AAED,oFAAoF;AACpF,wBAAsB,0BAA0B,CAAC,IAAI,EAAE;IACrD,GAAG,EAAE,cAAc,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiDlB;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,GAAG,EAAE,cAAc,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+BhB;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,GAAG,EAAE,cAAc,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuChB"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { collectionOf } from '../../collections/helpers';
|
|
2
2
|
import { CTX_CASCADING_REVOKE, CTX_SYSTEM_REQUEST } from './contextFlags';
|
|
3
3
|
import { evaluateRules, ruleGroupHasProgressRequirements } from './evaluateRules';
|
|
4
|
+
import { transitionLogData } from './logData';
|
|
4
5
|
import { recordLog, syncTierChangedLog } from './recordEvent';
|
|
5
6
|
import { relationId } from './relationId';
|
|
6
7
|
import { syncTierProgression } from './tierProgression';
|
|
@@ -209,10 +210,10 @@ export async function runAfterGrantCreated(args) {
|
|
|
209
210
|
userId: args.userId,
|
|
210
211
|
scopeId: args.scopeId,
|
|
211
212
|
type: 'achievement.granted',
|
|
212
|
-
data: {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
},
|
|
213
|
+
data: transitionLogData({
|
|
214
|
+
from: null,
|
|
215
|
+
to: { id: args.achievementId, slug: args.achievementSlug },
|
|
216
|
+
}),
|
|
216
217
|
});
|
|
217
218
|
await syncCompositeProgression({
|
|
218
219
|
req: args.req,
|
|
@@ -238,10 +239,10 @@ export async function runAfterGrantDeleted(args) {
|
|
|
238
239
|
userId: args.userId,
|
|
239
240
|
scopeId: args.scopeId,
|
|
240
241
|
type: 'achievement.revoked',
|
|
241
|
-
data: {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
},
|
|
242
|
+
data: transitionLogData({
|
|
243
|
+
from: { id: args.achievementId, slug: args.achievementSlug },
|
|
244
|
+
to: null,
|
|
245
|
+
}),
|
|
245
246
|
});
|
|
246
247
|
if (args.cascading)
|
|
247
248
|
return;
|
|
@@ -17,4 +17,6 @@ export { reconcileProgression, reconcileUserProgression } from './reconcile';
|
|
|
17
17
|
export type { ReconcileProgressionArgs, ReconcileProgressionResult } from './reconcile';
|
|
18
18
|
export { didDisableRequiresReview, releasePendingAchievementReviews, releasePendingTierReviews, } from './releaseReviewGate';
|
|
19
19
|
export type { ReleaseReviewGateResult } from './releaseReviewGate';
|
|
20
|
+
export { catalogRef, transitionLogData, transitionToId, } from './logData';
|
|
21
|
+
export type { CatalogRef, TransitionLogData } from './logData';
|
|
20
22
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/achievement/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,8BAA8B,EAAE,MAAM,iBAAiB,CAAA;AACzH,YAAY,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AACxE,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAA;AACzE,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAA;AAC7F,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAC9F,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAC3D,YAAY,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAC/D,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAA;AACvF,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAA;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AAC5E,YAAY,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAA;AACvF,OAAO,EACL,wBAAwB,EACxB,gCAAgC,EAChC,yBAAyB,GAC1B,MAAM,qBAAqB,CAAA;AAC5B,YAAY,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/achievement/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,8BAA8B,EAAE,MAAM,iBAAiB,CAAA;AACzH,YAAY,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AACxE,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAA;AACzE,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAA;AAC7F,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAC9F,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAC3D,YAAY,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAC/D,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAA;AACvF,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAA;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AAC5E,YAAY,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAA;AACvF,OAAO,EACL,wBAAwB,EACxB,gCAAgC,EAChC,yBAAyB,GAC1B,MAAM,qBAAqB,CAAA;AAC5B,YAAY,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAClE,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,cAAc,GACf,MAAM,WAAW,CAAA;AAClB,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA"}
|
|
@@ -11,3 +11,4 @@ export { syncCompositeProgression } from './grantSideEffects';
|
|
|
11
11
|
export { syncTierProgression } from './tierProgression';
|
|
12
12
|
export { reconcileProgression, reconcileUserProgression } from './reconcile';
|
|
13
13
|
export { didDisableRequiresReview, releasePendingAchievementReviews, releasePendingTierReviews, } from './releaseReviewGate';
|
|
14
|
+
export { catalogRef, transitionLogData, transitionToId, } from './logData';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared engine shape for achievement-log `data` on system event types.
|
|
3
|
+
* Hosts may add extra keys; readers should treat unknown keys as opaque.
|
|
4
|
+
*
|
|
5
|
+
* Transition events always use `from` / `to` (either side may be null):
|
|
6
|
+
* - `tier.changed` — previous ladder step → current step
|
|
7
|
+
* - `achievement.granted` — `from: null`, `to: achievement`
|
|
8
|
+
* - `achievement.revoked` — `from: achievement`, `to: null`
|
|
9
|
+
*/
|
|
10
|
+
export type CatalogRef = {
|
|
11
|
+
id: string;
|
|
12
|
+
slug?: string;
|
|
13
|
+
};
|
|
14
|
+
export type TransitionLogData = {
|
|
15
|
+
from: CatalogRef | null;
|
|
16
|
+
to: CatalogRef | null;
|
|
17
|
+
};
|
|
18
|
+
export declare function catalogRef(id: string, slug?: string | null): CatalogRef;
|
|
19
|
+
export declare function transitionLogData(args: {
|
|
20
|
+
from?: {
|
|
21
|
+
id: string;
|
|
22
|
+
slug?: string | null;
|
|
23
|
+
} | null;
|
|
24
|
+
to?: {
|
|
25
|
+
id: string;
|
|
26
|
+
slug?: string | null;
|
|
27
|
+
} | null;
|
|
28
|
+
}): TransitionLogData;
|
|
29
|
+
/** Read the “current” catalog id from a log `data` blob (new or legacy shapes). */
|
|
30
|
+
export declare function transitionToId(data: unknown): string | null;
|
|
31
|
+
//# sourceMappingURL=logData.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logData.d.ts","sourceRoot":"","sources":["../../../src/services/achievement/logData.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;IACvB,EAAE,EAAE,UAAU,GAAG,IAAI,CAAA;CACtB,CAAA;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,UAAU,CAKvE;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,IAAI,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAA;IAClD,EAAE,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAA;CACjD,GAAG,iBAAiB,CAKpB;AAED,mFAAmF;AACnF,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAY3D"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export function catalogRef(id, slug) {
|
|
2
|
+
return {
|
|
3
|
+
id,
|
|
4
|
+
...(typeof slug === 'string' && slug.length > 0 ? { slug } : {}),
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
export function transitionLogData(args) {
|
|
8
|
+
return {
|
|
9
|
+
from: args.from ? catalogRef(args.from.id, args.from.slug) : null,
|
|
10
|
+
to: args.to ? catalogRef(args.to.id, args.to.slug) : null,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/** Read the “current” catalog id from a log `data` blob (new or legacy shapes). */
|
|
14
|
+
export function transitionToId(data) {
|
|
15
|
+
if (!data || typeof data !== 'object' || Array.isArray(data))
|
|
16
|
+
return null;
|
|
17
|
+
const record = data;
|
|
18
|
+
const to = record.to;
|
|
19
|
+
if (to && typeof to === 'object' && !Array.isArray(to)) {
|
|
20
|
+
const id = to.id;
|
|
21
|
+
if (typeof id === 'string' && id)
|
|
22
|
+
return id;
|
|
23
|
+
}
|
|
24
|
+
// Legacy tier.changed / achievement.* shapes
|
|
25
|
+
if (typeof record.tier === 'string' && record.tier)
|
|
26
|
+
return record.tier;
|
|
27
|
+
if (typeof record.achievement === 'string' && record.achievement)
|
|
28
|
+
return record.achievement;
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../../../src/services/achievement/reconcile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAS,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../../../src/services/achievement/reconcile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAS,MAAM,SAAS,CAAA;AAa7D,MAAM,MAAM,0BAA0B,GAAG;IACvC,YAAY,EAAE,MAAM,CAAA;IACpB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,iBAAiB,EAAE,MAAM,CAAA;IACzB,0BAA0B,EAAE,MAAM,CAAA;IAClC,mBAAmB,EAAE,MAAM,CAAA;IAC3B,eAAe,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,OAAO,EAAE,OAAO,CAAA;IAChB,GAAG,CAAC,EAAE,cAAc,CAAA;IACpB,2BAA2B;IAC3B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAwFD,wFAAwF;AACxF,wBAAsB,wBAAwB,CAAC,IAAI,EAAE;IACnD,OAAO,EAAE,OAAO,CAAA;IAChB,GAAG,CAAC,EAAE,cAAc,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB,GAAG,OAAO,CAAC,IAAI,CAAC,0BAA0B,EAAE,cAAc,CAAC,CAAC,CAoC5D;AA2LD;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,wBAAwB,GAC7B,OAAO,CAAC,0BAA0B,CAAC,CA8CrC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { collectionOf } from '../../collections/helpers';
|
|
2
2
|
import { syncCompositeProgression, } from './grantSideEffects';
|
|
3
|
+
import { transitionLogData, transitionToId } from './logData';
|
|
3
4
|
import { recordLog, syncTierChangedLog } from './recordEvent';
|
|
4
5
|
import { relationId } from './relationId';
|
|
5
6
|
import { resolveCatalogId } from './resolveCatalog';
|
|
@@ -33,7 +34,7 @@ async function backfillGrantedLogs(args) {
|
|
|
33
34
|
},
|
|
34
35
|
});
|
|
35
36
|
const logged = new Set(logs.docs
|
|
36
|
-
.map((log) =>
|
|
37
|
+
.map((log) => transitionToId(log.data))
|
|
37
38
|
.filter((id) => Boolean(id)));
|
|
38
39
|
let written = 0;
|
|
39
40
|
for (const grant of grants.docs) {
|
|
@@ -63,10 +64,12 @@ async function backfillGrantedLogs(args) {
|
|
|
63
64
|
scopeId: args.scopeId,
|
|
64
65
|
type: 'achievement.granted',
|
|
65
66
|
data: {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
...transitionLogData({
|
|
68
|
+
from: null,
|
|
69
|
+
to: { id: achievementId, slug },
|
|
70
|
+
}),
|
|
69
71
|
...(completedAt ? { completedAt } : {}),
|
|
72
|
+
backfilled: true,
|
|
70
73
|
},
|
|
71
74
|
});
|
|
72
75
|
logged.add(achievementId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recordEvent.d.ts","sourceRoot":"","sources":["../../../src/services/achievement/recordEvent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAWtD,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,OAAO,CAAA;IAChB,GAAG,CAAC,EAAE,cAAc,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;CACtC,CAAA;AAgBD,6DAA6D;AAC7D,wBAAsB,SAAS,CAAC,IAAI,EAAE,cAAc,wEAuCnD;AAED,4CAA4C;AAC5C,eAAO,MAAM,WAAW,kBAAY,CAAA;AAEpC;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,OAAO,EAAE,OAAO,CAAA;IAChB,GAAG,CAAC,EAAE,cAAc,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB,wEAiCA;AAED,6FAA6F;AAC7F,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,OAAO,EAAE,OAAO,CAAA;IAChB,GAAG,CAAC,EAAE,cAAc,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB,
|
|
1
|
+
{"version":3,"file":"recordEvent.d.ts","sourceRoot":"","sources":["../../../src/services/achievement/recordEvent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAWtD,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,OAAO,CAAA;IAChB,GAAG,CAAC,EAAE,cAAc,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;CACtC,CAAA;AAgBD,6DAA6D;AAC7D,wBAAsB,SAAS,CAAC,IAAI,EAAE,cAAc,wEAuCnD;AAED,4CAA4C;AAC5C,eAAO,MAAM,WAAW,kBAAY,CAAA;AAEpC;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,OAAO,EAAE,OAAO,CAAA;IAChB,GAAG,CAAC,EAAE,cAAc,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB,wEAiCA;AAED,6FAA6F;AAC7F,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,OAAO,EAAE,OAAO,CAAA;IAChB,GAAG,CAAC,EAAE,cAAc,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB,iFA0DA"}
|
|
@@ -2,8 +2,8 @@ import { APIError } from 'payload';
|
|
|
2
2
|
import { DEFAULT_ACHIEVEMENT_METRIC_SLUG } from '../../catalog';
|
|
3
3
|
import { collectionOf } from '../../collections/helpers';
|
|
4
4
|
import { eventTypeRequiresActor } from './eventTypeRequiresActor';
|
|
5
|
+
import { transitionLogData, transitionToId } from './logData';
|
|
5
6
|
import { resolveCatalogId } from './resolveCatalog';
|
|
6
|
-
import { relationId } from './relationId';
|
|
7
7
|
import { resolveCurrentTier } from './resolveCurrentTier';
|
|
8
8
|
import { userScopeWhere } from './where';
|
|
9
9
|
async function catalogId(args) {
|
|
@@ -113,22 +113,35 @@ export async function syncTierChangedLog(args) {
|
|
|
113
113
|
and: [userScopeWhere(args.userId, scopeId), { type: { equals: typeId } }],
|
|
114
114
|
},
|
|
115
115
|
});
|
|
116
|
-
const
|
|
116
|
+
const latestData = latest.docs[0]?.data;
|
|
117
|
+
const lastTierId = transitionToId(latestData);
|
|
117
118
|
const currentId = current?.id ?? null;
|
|
118
119
|
if (lastTierId === currentId)
|
|
119
120
|
return null;
|
|
120
121
|
if (!currentId)
|
|
121
122
|
return null;
|
|
123
|
+
let fromSlug;
|
|
124
|
+
if (latestData && typeof latestData === 'object' && !Array.isArray(latestData)) {
|
|
125
|
+
const record = latestData;
|
|
126
|
+
const to = record.to;
|
|
127
|
+
if (to && typeof to === 'object' && !Array.isArray(to)) {
|
|
128
|
+
const slug = to.slug;
|
|
129
|
+
if (typeof slug === 'string')
|
|
130
|
+
fromSlug = slug;
|
|
131
|
+
}
|
|
132
|
+
else if (typeof record.tierSlug === 'string') {
|
|
133
|
+
fromSlug = record.tierSlug;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
122
136
|
return recordLog({
|
|
123
137
|
payload: args.payload,
|
|
124
138
|
req: args.req,
|
|
125
139
|
userId: args.userId,
|
|
126
140
|
scopeId,
|
|
127
141
|
type: 'tier.changed',
|
|
128
|
-
data: {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
},
|
|
142
|
+
data: transitionLogData({
|
|
143
|
+
from: lastTierId ? { id: lastTierId, slug: fromSlug } : null,
|
|
144
|
+
to: { id: currentId, slug: current?.slug },
|
|
145
|
+
}),
|
|
133
146
|
});
|
|
134
147
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dappermountain/payload-plugin-achievements",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "A robust, Admin-configured achievements engine for Payload: composable unlock rules, derived rank progress, request/review grants, metrics, and scoped multi-tenant support.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|