@dappermountain/payload-plugin-achievements 0.2.6 → 0.2.7
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 +34 -8
- package/dist/catalog.d.ts +1 -0
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +1 -1
- package/dist/cli/reconcile.d.ts.map +1 -1
- package/dist/cli/reconcile.js +1 -0
- package/dist/collections/MetricBalances/access/index.d.ts +4 -0
- package/dist/collections/MetricBalances/access/index.d.ts.map +1 -0
- package/dist/collections/MetricBalances/access/index.js +9 -0
- package/dist/collections/MetricBalances/hooks/index.d.ts +3 -0
- package/dist/collections/MetricBalances/hooks/index.d.ts.map +1 -0
- package/dist/collections/MetricBalances/hooks/index.js +1 -0
- package/dist/collections/MetricBalances/index.d.ts +3 -0
- package/dist/collections/MetricBalances/index.d.ts.map +1 -0
- package/dist/collections/MetricBalances/index.js +48 -0
- package/dist/collections/Metrics/index.d.ts.map +1 -1
- package/dist/collections/Metrics/index.js +64 -3
- package/dist/collections/fields/ruleFields.d.ts.map +1 -1
- package/dist/collections/fields/ruleFields.js +45 -2
- package/dist/collections/hooks/preventCatalogDelete.d.ts.map +1 -1
- package/dist/collections/hooks/preventCatalogDelete.js +10 -1
- package/dist/collections/index.d.ts.map +1 -1
- package/dist/collections/index.js +2 -0
- package/dist/collections/slugs.d.ts.map +1 -1
- package/dist/collections/slugs.js +1 -0
- package/dist/defaults.d.ts +4 -0
- package/dist/defaults.d.ts.map +1 -1
- package/dist/defaults.js +10 -0
- package/dist/endpoints/index.d.ts.map +1 -1
- package/dist/endpoints/index.js +4 -0
- package/dist/endpoints/leaderboard.d.ts +6 -0
- package/dist/endpoints/leaderboard.d.ts.map +1 -0
- package/dist/endpoints/leaderboard.js +59 -0
- package/dist/extensions/elapsedSinceOptions.d.ts +7 -0
- package/dist/extensions/elapsedSinceOptions.d.ts.map +1 -0
- package/dist/extensions/elapsedSinceOptions.js +16 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +9 -0
- package/dist/seed/index.d.ts +10 -0
- package/dist/seed/index.d.ts.map +1 -1
- package/dist/seed/index.js +14 -2
- package/dist/services/achievement/builtInRules.d.ts.map +1 -1
- package/dist/services/achievement/builtInRules.js +59 -21
- package/dist/services/achievement/duration.d.ts +6 -0
- package/dist/services/achievement/duration.d.ts.map +1 -0
- package/dist/services/achievement/duration.js +43 -0
- package/dist/services/achievement/getMetricLeaderboard.d.ts +30 -0
- package/dist/services/achievement/getMetricLeaderboard.d.ts.map +1 -0
- package/dist/services/achievement/getMetricLeaderboard.js +62 -0
- package/dist/services/achievement/index.d.ts +5 -0
- package/dist/services/achievement/index.d.ts.map +1 -1
- package/dist/services/achievement/index.js +4 -0
- package/dist/services/achievement/metricBalances.d.ts +42 -0
- package/dist/services/achievement/metricBalances.d.ts.map +1 -0
- package/dist/services/achievement/metricBalances.js +137 -0
- package/dist/services/achievement/reconcile.d.ts +1 -0
- package/dist/services/achievement/reconcile.d.ts.map +1 -1
- package/dist/services/achievement/reconcile.js +10 -0
- package/dist/services/achievement/recordEvent.d.ts.map +1 -1
- package/dist/services/achievement/recordEvent.js +22 -1
- package/dist/services/achievement/resolveElapsedAnchor.d.ts +15 -0
- package/dist/services/achievement/resolveElapsedAnchor.d.ts.map +1 -0
- package/dist/services/achievement/resolveElapsedAnchor.js +98 -0
- package/dist/services/achievement/resolveMetricValue.d.ts +32 -0
- package/dist/services/achievement/resolveMetricValue.d.ts.map +1 -0
- package/dist/services/achievement/resolveMetricValue.js +73 -0
- package/dist/services/achievement/validateRules.d.ts.map +1 -1
- package/dist/services/achievement/validateRules.js +19 -0
- package/dist/types.d.ts +26 -3
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -79,7 +79,8 @@ Slugs are prefixed with `achievement-` by default so they don’t collide with y
|
|
|
79
79
|
|
|
80
80
|
| Config key | Default slug | Purpose |
|
|
81
81
|
| --- | --- | --- |
|
|
82
|
-
| `metrics` | `achievement-metrics` | Named
|
|
82
|
+
| `metrics` | `achievement-metrics` | Named numbers: **stored** (score totals) or **computed** (e.g. elapsed days). |
|
|
83
|
+
| `metricBalances` | `achievement-metric-balances` | Projection of stored metric totals per user (+ scope) for fast reads / leaderboards. |
|
|
83
84
|
| `eventTypes` | `achievement-event-types` | Kinds of log entries you can count or require. |
|
|
84
85
|
| `tiers` | `achievement-tiers` | Ordered ladder steps with unlock rules. |
|
|
85
86
|
| `achievements` | `achievement-definitions` | Things a user can earn (with eligibility / completion rules). |
|
|
@@ -106,7 +107,7 @@ Unlock (tiers), eligibility, and completion (achievements) share the same rule t
|
|
|
106
107
|
|
|
107
108
|
- Top-level empty list → everyone passes
|
|
108
109
|
- Nested groups → AND (“all of these”) or OR (“any of these”)
|
|
109
|
-
- Built-in leaves → `tier-at-least`, `achievement-complete`, `metric-minimum`, `event-count`
|
|
110
|
+
- Built-in leaves → `tier-at-least`, `achievement-complete`, `metric-minimum`, `event-count`, `elapsed-since`
|
|
110
111
|
- Custom leaves → register via `extensions.ruleTypes`
|
|
111
112
|
|
|
112
113
|
**Current tier** is computed by walking tiers in `rank` order and evaluating each tier’s unlock rules (`resolveCurrentTier`). Tiers with **`requiresReview`** only become current after an **approved tier request**. **Next-tier fill** uses fractional progress on the same trees (`resolveTierProgress` / `evaluateRuleProgress`):
|
|
@@ -116,9 +117,17 @@ Unlock (tiers), eligibility, and completion (achievements) share the same rule t
|
|
|
116
117
|
| AND | Equal average of *requirement* children |
|
|
117
118
|
| OR | Best child (max) |
|
|
118
119
|
| `tier-at-least` | Gate — skipped in AND averages |
|
|
119
|
-
| `event-count` / `metric-minimum` | Fraction of the target |
|
|
120
|
+
| `event-count` / `metric-minimum` / `elapsed-since` | Fraction of the target |
|
|
120
121
|
| `achievement-complete` | `1` if granted; otherwise rolls up that achievement’s completion (or eligibility) rules |
|
|
121
122
|
|
|
123
|
+
**`elapsed-since`** — time since an anchor ≥ amount (unit: `days` | `hours` | `minutes`). Built-in anchors: user `createdAt`, or earliest log of an event type (`since: 'first-event'`). Hosts register more anchors via `extensions.metricAnchors` (same keys work on computed metrics).
|
|
124
|
+
|
|
125
|
+
**Stored vs computed metrics** — `kind: stored` (default) totals live in `achievement-metric-balances`, updated by `recordMetricChange` (log + balance dual-write). Logs remain the audit/rebuild source; reconcile backfills balances. `kind: computed` + `compute: elapsed` exposes a live number (e.g. days since an anchor); use `metric-minimum` against it. System seed only creates stored `points` — product computed metrics (e.g. `days`) are host-seeded after registering anchors.
|
|
126
|
+
|
|
127
|
+
**Leaderboards** — `getMetricLeaderboard` / `GET /api/achievements/leaderboard?metric=points` ranks stored balances (authenticated). Disable with `endpoints.leaderboard: false`.
|
|
128
|
+
|
|
129
|
+
**System catalog** — by default the plugin runs `seedAchievementCatalog` on Payload `onInit` (opt out with `seedSystemCatalog: false`). Hosts still seed product catalog + locales via `seedAchievements`.
|
|
130
|
+
|
|
122
131
|
**Eligibility rules** gate who may request an achievement. **Completion rules** define what a composed achievement is made of. When `requiresReview` is false and completion rules pass, the parent can auto-grant. Cycles in nested achievement graphs are ignored.
|
|
123
132
|
|
|
124
133
|
### Access model
|
|
@@ -159,8 +168,11 @@ achievementPlugin({
|
|
|
159
168
|
overrides?: Partial<Record<AchievementCollectionKey, AchievementCollectionOverride>>
|
|
160
169
|
}
|
|
161
170
|
users?: { includeJoins?: boolean }
|
|
162
|
-
endpoints?: { me?: string | false }
|
|
163
|
-
extensions?: {
|
|
171
|
+
endpoints?: { me?: string | false; leaderboard?: string | false; reconcile?: string | false }
|
|
172
|
+
extensions?: {
|
|
173
|
+
ruleTypes?: AchievementRuleType[]
|
|
174
|
+
metricAnchors?: Record<string, AchievementMetricAnchor>
|
|
175
|
+
}
|
|
164
176
|
})
|
|
165
177
|
```
|
|
166
178
|
|
|
@@ -169,10 +181,12 @@ achievementPlugin({
|
|
|
169
181
|
| Option | Default | Notes |
|
|
170
182
|
| --- | --- | --- |
|
|
171
183
|
| `enabled` | `true` | Set `false` to leave the plugin installed but inactive (no collections / endpoints merged). |
|
|
184
|
+
| `seedSystemCatalog` | `true` | On `onInit`, upsert system metrics + event types (`points`, `metric.delta`, …). |
|
|
172
185
|
| `usersCollectionSlug` | `'users'` | Users collection the plugin relates to (grants, requests, joins). |
|
|
173
186
|
| `canReview` | _(denied)_ | **Important.** Without this, users cannot manage catalogs or approve requests. Receives `(user, scopeId)` where `scopeId` may be `null`. |
|
|
174
187
|
| `scope` | _(none)_ | Multi-tenant hook-up. `collection` is the relation target (e.g. `'tenants'`). `relationField` defaults to `'scope'`. Adds an optional scope field across plugin collections. |
|
|
175
188
|
| `mediaCollection` | _(none)_ | When set (e.g. `'media'`), tiers get an optional upload field for ladder badge images. Icon string keys still work without this. |
|
|
189
|
+
| `extensions.metricAnchors` | _(none)_ | Named `(ctx) => Date | null` resolvers for computed elapsed metrics / `elapsed-since`. Keys appear in Admin `since` selects. |
|
|
176
190
|
|
|
177
191
|
### `collections`
|
|
178
192
|
|
|
@@ -217,17 +231,25 @@ achievementPlugin({
|
|
|
217
231
|
| Option | Default | Notes |
|
|
218
232
|
| --- | --- | --- |
|
|
219
233
|
| `me` | `'/achievements/me'` | Registers `GET /api/achievements/me` for the signed-in user’s grants snapshot (+ derived tiers and lean requests). Pass `false` to skip. Having review access does **not** widen this endpoint to other users. |
|
|
234
|
+
| `leaderboard` | `'/achievements/leaderboard'` | Registers `GET /api/achievements/leaderboard?metric=<slug>` for authenticated users (stored metrics only). Pass `false` to skip. |
|
|
235
|
+
| `reconcile` | `'/achievements/reconcile'` | Registers `POST /api/achievements/reconcile` for reviewers. Pass `false` to skip. |
|
|
220
236
|
|
|
221
|
-
Query params: `scope`, `limit`, `page`, `requestsLimit`.
|
|
237
|
+
Query params (`me`): `scope`, `limit`, `page`, `requestsLimit`. Leaderboard: `metric` (required), `scope`, `limit`, `page`.
|
|
222
238
|
|
|
223
|
-
### `extensions.ruleTypes`
|
|
239
|
+
### `extensions.ruleTypes` / `metricAnchors`
|
|
224
240
|
|
|
225
|
-
Register custom rule evaluators
|
|
241
|
+
Register custom rule evaluators and/or date anchors:
|
|
226
242
|
|
|
227
243
|
```ts
|
|
228
244
|
achievementPlugin({
|
|
229
245
|
canReview,
|
|
230
246
|
extensions: {
|
|
247
|
+
metricAnchors: {
|
|
248
|
+
'membership-granted': async ({ payload, userId, scopeId }) => {
|
|
249
|
+
// return a Date from host data, or null
|
|
250
|
+
return null
|
|
251
|
+
},
|
|
252
|
+
},
|
|
231
253
|
ruleTypes: [
|
|
232
254
|
{
|
|
233
255
|
type: 'host.custom-check',
|
|
@@ -251,6 +273,8 @@ Use these from hooks, jobs, and trusted endpoints — not from the public client
|
|
|
251
273
|
import {
|
|
252
274
|
recordLog,
|
|
253
275
|
recordMetricChange,
|
|
276
|
+
getMetricLeaderboard,
|
|
277
|
+
resolveMetricValue,
|
|
254
278
|
grantAchievement,
|
|
255
279
|
reconcileProgression,
|
|
256
280
|
reconcileUserProgression,
|
|
@@ -263,6 +287,7 @@ import {
|
|
|
263
287
|
|
|
264
288
|
await recordLog({ payload, userId, scopeId, type: 'host.custom-kind', actorId })
|
|
265
289
|
await recordMetricChange({ payload, userId, scopeId, metric: 'points', change: 10 })
|
|
290
|
+
const board = await getMetricLeaderboard({ payload, metric: 'points', scopeId, limit: 20 })
|
|
266
291
|
const tier = await resolveCurrentTier({ payload, userId, scopeId })
|
|
267
292
|
|
|
268
293
|
// Repair users whose grants predate side-effect hooks (idempotent)
|
|
@@ -306,6 +331,7 @@ Turning **Requires review** off on a definition or tier **approves pending reque
|
|
|
306
331
|
| Goal | Request |
|
|
307
332
|
| --- | --- |
|
|
308
333
|
| Current user snapshot | `GET /api/achievements/me?scope=<scopeId>&limit=10&page=1` |
|
|
334
|
+
| Stored metric leaderboard | `GET /api/achievements/leaderboard?metric=points&scope=<scopeId>&limit=20&page=1` |
|
|
309
335
|
| Repair progression | `POST /api/achievements/reconcile` (reviewer; optional `{ userId, scopeId, achievementId\|achievementSlug, tierId\|tierSlug, limit }`) |
|
|
310
336
|
| List grants | `GET /api/achievement-grants?where[user][equals]=<userId>` |
|
|
311
337
|
| Log history | `GET /api/achievement-logs?where[user][equals]=<userId>` |
|
package/dist/catalog.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export declare const ENGINE_EVENT_TYPES: readonly [{
|
|
|
15
15
|
export declare const ENGINE_METRICS: readonly [{
|
|
16
16
|
readonly slug: "points";
|
|
17
17
|
readonly name: "Points";
|
|
18
|
+
readonly kind: "stored";
|
|
18
19
|
}];
|
|
19
20
|
export type EngineEventTypeSlug = (typeof ENGINE_EVENT_TYPES)[number]['slug'];
|
|
20
21
|
export type EngineMetricSlug = (typeof ENGINE_METRICS)[number]['slug'];
|
package/dist/catalog.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;EAKrB,CAAA;AAEV,eAAO,MAAM,cAAc
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;EAKrB,CAAA;AAEV,eAAO,MAAM,cAAc;;;;EAAyE,CAAA;AAEpG,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;AAC7E,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;AAEtE,eAAO,MAAM,+BAA+B,EAAE,gBAA2B,CAAA;AAEzE,+DAA+D;AAC/D,eAAO,MAAM,0BAA0B,UAAkC,CAAA"}
|
package/dist/catalog.js
CHANGED
|
@@ -4,7 +4,7 @@ export const ENGINE_EVENT_TYPES = [
|
|
|
4
4
|
{ slug: 'metric.delta', name: 'Metric delta', requiresMetric: true },
|
|
5
5
|
{ slug: 'tier.changed', name: 'Tier changed' },
|
|
6
6
|
];
|
|
7
|
-
export const ENGINE_METRICS = [{ slug: 'points', name: 'Points' }];
|
|
7
|
+
export const ENGINE_METRICS = [{ slug: 'points', name: 'Points', kind: 'stored' }];
|
|
8
8
|
export const DEFAULT_ACHIEVEMENT_METRIC_SLUG = 'points';
|
|
9
9
|
/** @deprecated Use {@link DEFAULT_ACHIEVEMENT_METRIC_SLUG}. */
|
|
10
10
|
export const DEFAULT_ACHIEVEMENT_METRIC = DEFAULT_ACHIEVEMENT_METRIC_SLUG;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../../src/cli/reconcile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,SAAS,CAAA;AAE1D,OAAO,EAEL,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAChC,MAAM,sCAAsC,CAAA;AAE7C,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,wBAAwB,EAAE,SAAS,GAAG,KAAK,CAAC,CAAA;AA2BnF,sFAAsF;AACtF,wBAAgB,qBAAqB,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,mBAAmB,CAUjG;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAc5C;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;IAClD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,OAAO,CAAC,EAAE,mBAAmB,CAAA;IAC7B,kFAAkF;IAClF,IAAI,CAAC,EAAE,OAAO,CAAA;CACf,GAAG,OAAO,CAAC,0BAA0B,CAAC,
|
|
1
|
+
{"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../../src/cli/reconcile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,SAAS,CAAA;AAE1D,OAAO,EAEL,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAChC,MAAM,sCAAsC,CAAA;AAE7C,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,wBAAwB,EAAE,SAAS,GAAG,KAAK,CAAC,CAAA;AA2BnF,sFAAsF;AACtF,wBAAgB,qBAAqB,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,mBAAmB,CAUjG;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAc5C;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;IAClD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,OAAO,CAAC,EAAE,mBAAmB,CAAA;IAC7B,kFAAkF;IAClF,IAAI,CAAC,EAAE,OAAO,CAAA;CACf,GAAG,OAAO,CAAC,0BAA0B,CAAC,CA4BtC"}
|
package/dist/cli/reconcile.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/collections/MetricBalances/access/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAK/C,4EAA4E;AAC5E,eAAO,MAAM,MAAM,EAAE,WAAW,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAK1D,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { requireOne } from '../../../access/index.js';
|
|
2
|
+
import { isReviewer } from '../../../access/roles/index.js';
|
|
3
|
+
/** Projection rows — writes only via trusted helpers (`overrideAccess`). */
|
|
4
|
+
export const access = {
|
|
5
|
+
read: requireOne(isReviewer('metricBalances')),
|
|
6
|
+
create: () => false,
|
|
7
|
+
update: () => false,
|
|
8
|
+
delete: requireOne(isReviewer('metricBalances')),
|
|
9
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/collections/MetricBalances/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAE/C,eAAO,MAAM,KAAK,EAAE,gBAAgB,CAAC,OAAO,CAAM,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const hooks = {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/collections/MetricBalances/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAa/C,wBAAgB,6BAA6B,IAAI,gBAAgB,CA4ChE"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { collectionAdmin, collectionOf, columnsWithOptionalScope, optionalFields, slugOf, } from '../helpers.js';
|
|
2
|
+
import { scopeField, userField } from '../fields/index.js';
|
|
3
|
+
import { access } from './access/index.js';
|
|
4
|
+
import { hooks } from './hooks/index.js';
|
|
5
|
+
export function buildMetricBalancesCollection() {
|
|
6
|
+
return {
|
|
7
|
+
slug: slugOf('metricBalances'),
|
|
8
|
+
access: { ...access },
|
|
9
|
+
hooks,
|
|
10
|
+
admin: collectionAdmin({
|
|
11
|
+
useAsTitle: 'key',
|
|
12
|
+
defaultColumns: columnsWithOptionalScope(['metric', 'user', 'value', 'scope', 'updatedAt']),
|
|
13
|
+
description: 'Stored metric totals per user (and scope). Updated by recordMetricChange; repair with reconcile. Not for computed metrics.',
|
|
14
|
+
}),
|
|
15
|
+
fields: [
|
|
16
|
+
userField(),
|
|
17
|
+
...optionalFields(scopeField()),
|
|
18
|
+
{
|
|
19
|
+
name: 'metric',
|
|
20
|
+
type: 'relationship',
|
|
21
|
+
relationTo: collectionOf('metrics'),
|
|
22
|
+
required: true,
|
|
23
|
+
index: true,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'value',
|
|
27
|
+
type: 'number',
|
|
28
|
+
required: true,
|
|
29
|
+
defaultValue: 0,
|
|
30
|
+
index: true,
|
|
31
|
+
admin: {
|
|
32
|
+
description: 'Current total (sum of metric.delta changes).',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: 'key',
|
|
37
|
+
type: 'text',
|
|
38
|
+
required: true,
|
|
39
|
+
unique: true,
|
|
40
|
+
index: true,
|
|
41
|
+
admin: {
|
|
42
|
+
readOnly: true,
|
|
43
|
+
description: 'Stable unique key: user:scope:metric.',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/collections/Metrics/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/collections/Metrics/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAS/C,wBAAgB,sBAAsB,IAAI,gBAAgB,CA2FzD"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { collectionAdmin, columnsWithOptionalScope, optionalFields, slugOf } from '../helpers.js';
|
|
1
|
+
import { collectionAdmin, collectionOf, columnsWithOptionalScope, optionalFields, slugOf } from '../helpers.js';
|
|
2
2
|
import { localizedNameField, scopeField } from '../fields/index.js';
|
|
3
|
+
import { catalogFilterOptions } from '../fields/catalogFilter.js';
|
|
4
|
+
import { elapsedSinceSelectOptions } from '../../extensions/elapsedSinceOptions.js';
|
|
3
5
|
import { access } from './access/index.js';
|
|
4
6
|
import { hooks } from './hooks/index.js';
|
|
5
7
|
export function buildMetricsCollection() {
|
|
@@ -9,8 +11,8 @@ export function buildMetricsCollection() {
|
|
|
9
11
|
hooks,
|
|
10
12
|
admin: collectionAdmin({
|
|
11
13
|
useAsTitle: 'name',
|
|
12
|
-
defaultColumns: columnsWithOptionalScope(['name', 'slug', 'system', 'scope']),
|
|
13
|
-
description: '
|
|
14
|
+
defaultColumns: columnsWithOptionalScope(['name', 'slug', 'kind', 'system', 'scope']),
|
|
15
|
+
description: 'Named numbers. Stored metrics are score totals from log deltas; computed metrics are derived at evaluation time.',
|
|
14
16
|
}),
|
|
15
17
|
fields: [
|
|
16
18
|
...optionalFields(scopeField()),
|
|
@@ -21,6 +23,65 @@ export function buildMetricsCollection() {
|
|
|
21
23
|
{ name: 'slug', type: 'text', required: true, unique: true, index: true, admin: { width: '50%' } },
|
|
22
24
|
],
|
|
23
25
|
},
|
|
26
|
+
{
|
|
27
|
+
name: 'kind',
|
|
28
|
+
type: 'select',
|
|
29
|
+
required: true,
|
|
30
|
+
defaultValue: 'stored',
|
|
31
|
+
options: [
|
|
32
|
+
{ label: 'Stored (log deltas)', value: 'stored' },
|
|
33
|
+
{ label: 'Computed', value: 'computed' },
|
|
34
|
+
],
|
|
35
|
+
admin: {
|
|
36
|
+
description: 'Stored = sum of metric.delta logs (via balances). Computed = derived value.',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: 'compute',
|
|
41
|
+
type: 'select',
|
|
42
|
+
defaultValue: 'elapsed',
|
|
43
|
+
options: [{ label: 'Elapsed time', value: 'elapsed' }],
|
|
44
|
+
admin: {
|
|
45
|
+
condition: (_, sibling) => sibling?.kind === 'computed',
|
|
46
|
+
description: 'How this number is derived.',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: 'unit',
|
|
51
|
+
type: 'select',
|
|
52
|
+
defaultValue: 'days',
|
|
53
|
+
options: [
|
|
54
|
+
{ label: 'Days', value: 'days' },
|
|
55
|
+
{ label: 'Hours', value: 'hours' },
|
|
56
|
+
{ label: 'Minutes', value: 'minutes' },
|
|
57
|
+
],
|
|
58
|
+
admin: {
|
|
59
|
+
condition: (_, sibling) => sibling?.kind === 'computed' && sibling?.compute === 'elapsed',
|
|
60
|
+
description: 'Unit of the exposed number (e.g. whole days since the anchor).',
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: 'since',
|
|
65
|
+
type: 'select',
|
|
66
|
+
defaultValue: 'user-created-at',
|
|
67
|
+
options: elapsedSinceSelectOptions(),
|
|
68
|
+
admin: {
|
|
69
|
+
condition: (_, sibling) => sibling?.kind === 'computed' && sibling?.compute === 'elapsed',
|
|
70
|
+
description: 'Which timestamp starts the clock.',
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: 'eventType',
|
|
75
|
+
type: 'relationship',
|
|
76
|
+
relationTo: collectionOf('eventTypes'),
|
|
77
|
+
filterOptions: catalogFilterOptions,
|
|
78
|
+
admin: {
|
|
79
|
+
condition: (_, sibling) => sibling?.kind === 'computed' &&
|
|
80
|
+
sibling?.compute === 'elapsed' &&
|
|
81
|
+
sibling?.since === 'first-event',
|
|
82
|
+
description: 'Event type whose first log starts the clock.',
|
|
83
|
+
},
|
|
84
|
+
},
|
|
24
85
|
{
|
|
25
86
|
name: 'system',
|
|
26
87
|
type: 'checkbox',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ruleFields.d.ts","sourceRoot":"","sources":["../../../src/collections/fields/ruleFields.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"ruleFields.d.ts","sourceRoot":"","sources":["../../../src/collections/fields/ruleFields.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAkJpC;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,KAAK,EAAE,CAqB7C;AAED,mDAAmD;AACnD,wBAAgB,kBAAkB,IAAI,KAAK,EAAE,CAE5C"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { catalogFilterOptions } from './catalogFilter.js';
|
|
2
2
|
import { collectionOf } from '../helpers.js';
|
|
3
|
+
import { elapsedSinceSelectOptions } from '../../extensions/elapsedSinceOptions.js';
|
|
3
4
|
function combinatorField(visibleWhenGroup) {
|
|
4
5
|
return {
|
|
5
6
|
name: 'combinator',
|
|
@@ -25,6 +26,7 @@ function ruleTypeSelect(includeGroup) {
|
|
|
25
26
|
{ label: 'Achievement complete', value: 'achievement-complete' },
|
|
26
27
|
{ label: 'Metric minimum', value: 'metric-minimum' },
|
|
27
28
|
{ label: 'Event count', value: 'event-count' },
|
|
29
|
+
{ label: 'Elapsed since', value: 'elapsed-since' },
|
|
28
30
|
...(includeGroup ? [{ label: 'Group', value: 'group' }] : []),
|
|
29
31
|
],
|
|
30
32
|
};
|
|
@@ -75,8 +77,9 @@ function ruleParamFields() {
|
|
|
75
77
|
relationTo: collectionOf('eventTypes'),
|
|
76
78
|
filterOptions: catalogFilterOptions,
|
|
77
79
|
admin: {
|
|
78
|
-
condition: (_, sibling) => sibling?.type === 'event-count'
|
|
79
|
-
|
|
80
|
+
condition: (_, sibling) => sibling?.type === 'event-count' ||
|
|
81
|
+
(sibling?.type === 'elapsed-since' && sibling?.since === 'first-event'),
|
|
82
|
+
description: 'Event type to count, or (for elapsed since) the type whose first log starts the clock.',
|
|
80
83
|
},
|
|
81
84
|
},
|
|
82
85
|
{
|
|
@@ -87,6 +90,46 @@ function ruleParamFields() {
|
|
|
87
90
|
description: 'How many times it needs to have happened.',
|
|
88
91
|
},
|
|
89
92
|
},
|
|
93
|
+
{
|
|
94
|
+
name: 'since',
|
|
95
|
+
type: 'select',
|
|
96
|
+
defaultValue: 'user-created-at',
|
|
97
|
+
options: elapsedSinceSelectOptions(),
|
|
98
|
+
admin: {
|
|
99
|
+
condition: (_, sibling) => sibling?.type === 'elapsed-since',
|
|
100
|
+
description: 'Which timestamp starts the clock.',
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
type: 'row',
|
|
105
|
+
admin: {
|
|
106
|
+
condition: (_, sibling) => sibling?.type === 'elapsed-since',
|
|
107
|
+
},
|
|
108
|
+
fields: [
|
|
109
|
+
{
|
|
110
|
+
name: 'amount',
|
|
111
|
+
type: 'number',
|
|
112
|
+
admin: {
|
|
113
|
+
width: '50%',
|
|
114
|
+
description: 'How much time must pass.',
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
name: 'unit',
|
|
119
|
+
type: 'select',
|
|
120
|
+
defaultValue: 'days',
|
|
121
|
+
options: [
|
|
122
|
+
{ label: 'Days', value: 'days' },
|
|
123
|
+
{ label: 'Hours', value: 'hours' },
|
|
124
|
+
{ label: 'Minutes', value: 'minutes' },
|
|
125
|
+
],
|
|
126
|
+
admin: {
|
|
127
|
+
width: '50%',
|
|
128
|
+
description: 'Unit for the amount.',
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
},
|
|
90
133
|
];
|
|
91
134
|
}
|
|
92
135
|
function buildRuleLeafFields() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preventCatalogDelete.d.ts","sourceRoot":"","sources":["../../../src/collections/hooks/preventCatalogDelete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAA;AA6CzD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IACzC,IAAI,EAAE,WAAW,GAAG,QAAQ,CAAA;CAC7B,GAAG,0BAA0B,
|
|
1
|
+
{"version":3,"file":"preventCatalogDelete.d.ts","sourceRoot":"","sources":["../../../src/collections/hooks/preventCatalogDelete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAA;AA6CzD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IACzC,IAAI,EAAE,WAAW,GAAG,QAAQ,CAAA;CAC7B,GAAG,0BAA0B,CA+D7B"}
|
|
@@ -61,7 +61,8 @@ export function preventCatalogDelete(args) {
|
|
|
61
61
|
parts.push(`${logs.totalDocs} log row(s)`);
|
|
62
62
|
const rules = await countMatchingLeaves({
|
|
63
63
|
req,
|
|
64
|
-
match: (rule) => rule.type === 'event-count'
|
|
64
|
+
match: (rule) => (rule.type === 'event-count' || rule.type === 'elapsed-since') &&
|
|
65
|
+
relationId(rule.eventType) === id,
|
|
65
66
|
});
|
|
66
67
|
if (rules > 0)
|
|
67
68
|
parts.push(`${rules} rule(s)`);
|
|
@@ -75,6 +76,14 @@ export function preventCatalogDelete(args) {
|
|
|
75
76
|
});
|
|
76
77
|
if (logs.totalDocs > 0)
|
|
77
78
|
parts.push(`${logs.totalDocs} log row(s)`);
|
|
79
|
+
const balances = await req.payload.count({
|
|
80
|
+
collection: collectionOf('metricBalances'),
|
|
81
|
+
overrideAccess: true,
|
|
82
|
+
req,
|
|
83
|
+
where: { metric: { equals: id } },
|
|
84
|
+
});
|
|
85
|
+
if (balances.totalDocs > 0)
|
|
86
|
+
parts.push(`${balances.totalDocs} balance row(s)`);
|
|
78
87
|
const rules = await countMatchingLeaves({
|
|
79
88
|
req,
|
|
80
89
|
match: (rule) => rule.type === 'metric-minimum' && relationId(rule.metric) === id,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/collections/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/collections/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AA2B/C,qEAAqE;AACrE,wBAAgB,2BAA2B,IAAI,gBAAgB,EAAE,CAMhE"}
|
|
@@ -5,11 +5,13 @@ import { buildAchievementsCollection } from './Achievements/index.js';
|
|
|
5
5
|
import { buildEventTypesCollection } from './EventTypes/index.js';
|
|
6
6
|
import { buildGrantsCollection } from './Grants/index.js';
|
|
7
7
|
import { buildLogsCollection } from './Logs/index.js';
|
|
8
|
+
import { buildMetricBalancesCollection } from './MetricBalances/index.js';
|
|
8
9
|
import { buildMetricsCollection } from './Metrics/index.js';
|
|
9
10
|
import { buildTierRequestsCollection } from './TierRequests/index.js';
|
|
10
11
|
import { buildTiersCollection } from './Tiers/index.js';
|
|
11
12
|
const builders = {
|
|
12
13
|
metrics: buildMetricsCollection,
|
|
14
|
+
metricBalances: buildMetricBalancesCollection,
|
|
13
15
|
eventTypes: buildEventTypesCollection,
|
|
14
16
|
tiers: buildTiersCollection,
|
|
15
17
|
achievements: buildAchievementsCollection,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slugs.d.ts","sourceRoot":"","sources":["../../src/collections/slugs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AAErF;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,gBAAgB,CAAA;AAEtD;;;GAGG;AACH,eAAO,MAAM,6BAA6B,EAAE,MAAM,CAAC,wBAAwB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"slugs.d.ts","sourceRoot":"","sources":["../../src/collections/slugs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AAErF;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,gBAAgB,CAAA;AAEtD;;;GAGG;AACH,eAAO,MAAM,6BAA6B,EAAE,MAAM,CAAC,wBAAwB,EAAE,MAAM,CAUlF,CAAA;AAED,eAAO,MAAM,mBAAmB,iBAAiB,CAAA;AAEjD;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,GAAE,wBAA6B,GACrC,MAAM,CAAC,wBAAwB,EAAE,MAAM,CAAC,CAkB1C;AAED,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,wBAA6B,GAAG,MAAM,GAAG,KAAK,CAMxF"}
|
package/dist/defaults.d.ts
CHANGED
|
@@ -2,9 +2,11 @@ import type { AchievementPluginOptions } from './types.js';
|
|
|
2
2
|
import { resolveCollectionSlugs } from './collections/slugs.js';
|
|
3
3
|
export declare const DEFAULT_USERS_COLLECTION = "users";
|
|
4
4
|
export declare const DEFAULT_ME_ENDPOINT_PATH = "/achievements/me";
|
|
5
|
+
export declare const DEFAULT_LEADERBOARD_ENDPOINT_PATH = "/achievements/leaderboard";
|
|
5
6
|
export declare const DEFAULT_RECONCILE_ENDPOINT_PATH = "/achievements/reconcile";
|
|
6
7
|
export type ResolvedAchievementOptions = Omit<AchievementPluginOptions, 'users' | 'endpoints'> & {
|
|
7
8
|
enabled: boolean;
|
|
9
|
+
seedSystemCatalog: boolean;
|
|
8
10
|
usersCollectionSlug: string;
|
|
9
11
|
users: {
|
|
10
12
|
includeJoins: boolean;
|
|
@@ -15,10 +17,12 @@ export type ResolvedAchievementOptions = Omit<AchievementPluginOptions, 'users'
|
|
|
15
17
|
adminGroup: string | false;
|
|
16
18
|
endpoints: {
|
|
17
19
|
me: string | false;
|
|
20
|
+
leaderboard: string | false;
|
|
18
21
|
reconcile: string | false;
|
|
19
22
|
};
|
|
20
23
|
};
|
|
21
24
|
export declare function resolveMeEndpointPath(me?: string | false): string | false;
|
|
25
|
+
export declare function resolveLeaderboardEndpointPath(path?: string | false): string | false;
|
|
22
26
|
export declare function resolveReconcileEndpointPath(path?: string | false): string | false;
|
|
23
27
|
export declare function resolveOptions(options?: AchievementPluginOptions): ResolvedAchievementOptions;
|
|
24
28
|
//# sourceMappingURL=defaults.d.ts.map
|
package/dist/defaults.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAA;AAC1D,OAAO,EAEL,sBAAsB,EACvB,MAAM,wBAAwB,CAAA;AAE/B,eAAO,MAAM,wBAAwB,UAAU,CAAA;AAC/C,eAAO,MAAM,wBAAwB,qBAAqB,CAAA;AAC1D,eAAO,MAAM,+BAA+B,4BAA4B,CAAA;AAExE,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAAC,wBAAwB,EAAE,OAAO,GAAG,WAAW,CAAC,GAAG;IAC/F,OAAO,EAAE,OAAO,CAAA;IAChB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,KAAK,EAAE;QAAE,YAAY,EAAE,OAAO,CAAA;KAAE,CAAA;IAChC,+DAA+D;IAC/D,eAAe,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAA;IAC1D,oEAAoE;IACpE,UAAU,EAAE,MAAM,GAAG,KAAK,CAAA;IAC1B,SAAS,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,KAAK,CAAC;QAAC,SAAS,EAAE,MAAM,GAAG,KAAK,CAAA;KAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAA;AAC1D,OAAO,EAEL,sBAAsB,EACvB,MAAM,wBAAwB,CAAA;AAE/B,eAAO,MAAM,wBAAwB,UAAU,CAAA;AAC/C,eAAO,MAAM,wBAAwB,qBAAqB,CAAA;AAC1D,eAAO,MAAM,iCAAiC,8BAA8B,CAAA;AAC5E,eAAO,MAAM,+BAA+B,4BAA4B,CAAA;AAExE,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAAC,wBAAwB,EAAE,OAAO,GAAG,WAAW,CAAC,GAAG;IAC/F,OAAO,EAAE,OAAO,CAAA;IAChB,iBAAiB,EAAE,OAAO,CAAA;IAC1B,mBAAmB,EAAE,MAAM,CAAA;IAC3B,KAAK,EAAE;QAAE,YAAY,EAAE,OAAO,CAAA;KAAE,CAAA;IAChC,+DAA+D;IAC/D,eAAe,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAA;IAC1D,oEAAoE;IACpE,UAAU,EAAE,MAAM,GAAG,KAAK,CAAA;IAC1B,SAAS,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,KAAK,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,KAAK,CAAC;QAAC,SAAS,EAAE,MAAM,GAAG,KAAK,CAAA;KAAE,CAAA;CAC1F,CAAA;AAQD,wBAAgB,qBAAqB,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAIzE;AAED,wBAAgB,8BAA8B,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAIpF;AAED,wBAAgB,4BAA4B,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAIlF;AAED,wBAAgB,cAAc,CAAC,OAAO,GAAE,wBAA6B,GAAG,0BAA0B,CAiBjG"}
|
package/dist/defaults.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { resolveAdminGroup, resolveCollectionSlugs, } from './collections/slugs.js';
|
|
2
2
|
export const DEFAULT_USERS_COLLECTION = 'users';
|
|
3
3
|
export const DEFAULT_ME_ENDPOINT_PATH = '/achievements/me';
|
|
4
|
+
export const DEFAULT_LEADERBOARD_ENDPOINT_PATH = '/achievements/leaderboard';
|
|
4
5
|
export const DEFAULT_RECONCILE_ENDPOINT_PATH = '/achievements/reconcile';
|
|
5
6
|
function normalizeEndpointPath(path, fallback) {
|
|
6
7
|
const trimmed = path.trim();
|
|
@@ -15,6 +16,13 @@ export function resolveMeEndpointPath(me) {
|
|
|
15
16
|
return DEFAULT_ME_ENDPOINT_PATH;
|
|
16
17
|
return normalizeEndpointPath(me, DEFAULT_ME_ENDPOINT_PATH);
|
|
17
18
|
}
|
|
19
|
+
export function resolveLeaderboardEndpointPath(path) {
|
|
20
|
+
if (path === false)
|
|
21
|
+
return false;
|
|
22
|
+
if (path == null)
|
|
23
|
+
return DEFAULT_LEADERBOARD_ENDPOINT_PATH;
|
|
24
|
+
return normalizeEndpointPath(path, DEFAULT_LEADERBOARD_ENDPOINT_PATH);
|
|
25
|
+
}
|
|
18
26
|
export function resolveReconcileEndpointPath(path) {
|
|
19
27
|
if (path === false)
|
|
20
28
|
return false;
|
|
@@ -26,6 +34,7 @@ export function resolveOptions(options = {}) {
|
|
|
26
34
|
return {
|
|
27
35
|
...options,
|
|
28
36
|
enabled: options.enabled !== false,
|
|
37
|
+
seedSystemCatalog: options.seedSystemCatalog !== false,
|
|
29
38
|
usersCollectionSlug: options.usersCollectionSlug ?? DEFAULT_USERS_COLLECTION,
|
|
30
39
|
users: {
|
|
31
40
|
includeJoins: options.users?.includeJoins !== false,
|
|
@@ -34,6 +43,7 @@ export function resolveOptions(options = {}) {
|
|
|
34
43
|
adminGroup: resolveAdminGroup(options),
|
|
35
44
|
endpoints: {
|
|
36
45
|
me: resolveMeEndpointPath(options.endpoints?.me),
|
|
46
|
+
leaderboard: resolveLeaderboardEndpointPath(options.endpoints?.leaderboard),
|
|
37
47
|
reconcile: resolveReconcileEndpointPath(options.endpoints?.reconcile),
|
|
38
48
|
},
|
|
39
49
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/endpoints/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEvC,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/endpoints/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEvC,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAA;AAKhE,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,0BAA0B,GAAG,QAAQ,EAAE,CAYzF"}
|
package/dist/endpoints/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { buildLeaderboardEndpoint } from './leaderboard.js';
|
|
1
2
|
import { buildMeEndpoint } from './me.js';
|
|
2
3
|
import { buildReconcileEndpoint } from './reconcile.js';
|
|
3
4
|
export function buildAchievementEndpoints(options) {
|
|
@@ -5,6 +6,9 @@ export function buildAchievementEndpoints(options) {
|
|
|
5
6
|
if (options.endpoints.me !== false) {
|
|
6
7
|
endpoints.push(buildMeEndpoint(options.endpoints.me));
|
|
7
8
|
}
|
|
9
|
+
if (options.endpoints.leaderboard !== false) {
|
|
10
|
+
endpoints.push(buildLeaderboardEndpoint(options.endpoints.leaderboard));
|
|
11
|
+
}
|
|
8
12
|
if (options.endpoints.reconcile !== false) {
|
|
9
13
|
endpoints.push(buildReconcileEndpoint(options.endpoints.reconcile));
|
|
10
14
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Endpoint } from 'payload';
|
|
2
|
+
/**
|
|
3
|
+
* `GET` ranked stored-metric balances. Query: `metric` (required), optional `scope` / `limit` / `page`.
|
|
4
|
+
*/
|
|
5
|
+
export declare function buildLeaderboardEndpoint(path: string): Endpoint;
|
|
6
|
+
//# sourceMappingURL=leaderboard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leaderboard.d.ts","sourceRoot":"","sources":["../../src/endpoints/leaderboard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,SAAS,CAAA;AAsBvD;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAuC/D"}
|