@dappermountain/payload-plugin-achievements 0.5.0 → 0.6.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 (58) hide show
  1. package/README.md +278 -234
  2. package/dist/catalog.d.ts +3 -0
  3. package/dist/catalog.d.ts.map +1 -1
  4. package/dist/catalog.js +8 -0
  5. package/dist/collections/Grants/hooks/afterGrantMutation.d.ts.map +1 -1
  6. package/dist/collections/Grants/hooks/afterGrantMutation.js +15 -0
  7. package/dist/collections/Logs/hooks/afterLogMutation.d.ts +4 -0
  8. package/dist/collections/Logs/hooks/afterLogMutation.d.ts.map +1 -0
  9. package/dist/collections/Logs/hooks/afterLogMutation.js +47 -0
  10. package/dist/collections/Logs/hooks/index.d.ts.map +1 -1
  11. package/dist/collections/Logs/hooks/index.js +3 -0
  12. package/dist/collections/Logs/index.js +1 -1
  13. package/dist/collections/Reactions/access/index.d.ts +12 -0
  14. package/dist/collections/Reactions/access/index.d.ts.map +1 -0
  15. package/dist/collections/Reactions/access/index.js +2 -0
  16. package/dist/collections/Reactions/index.d.ts +3 -0
  17. package/dist/collections/Reactions/index.d.ts.map +1 -0
  18. package/dist/collections/Reactions/index.js +97 -0
  19. package/dist/collections/fields/ruleFields.d.ts.map +1 -1
  20. package/dist/collections/fields/ruleFields.js +19 -0
  21. package/dist/collections/fields/whenSibling.d.ts +7 -0
  22. package/dist/collections/fields/whenSibling.d.ts.map +1 -0
  23. package/dist/collections/fields/whenSibling.js +21 -0
  24. package/dist/collections/index.d.ts.map +1 -1
  25. package/dist/collections/index.js +2 -0
  26. package/dist/collections/slugs.d.ts.map +1 -1
  27. package/dist/collections/slugs.js +1 -0
  28. package/dist/defaults.d.ts +10 -1
  29. package/dist/defaults.d.ts.map +1 -1
  30. package/dist/defaults.js +34 -5
  31. package/dist/extensions/actions.d.ts +8 -0
  32. package/dist/extensions/actions.d.ts.map +1 -0
  33. package/dist/extensions/actions.js +26 -0
  34. package/dist/extensions/registry.d.ts +2 -0
  35. package/dist/extensions/registry.d.ts.map +1 -1
  36. package/dist/extensions/registry.js +19 -0
  37. package/dist/index.d.ts +4 -4
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +3 -3
  40. package/dist/plugin.d.ts.map +1 -1
  41. package/dist/plugin.js +9 -3
  42. package/dist/services/achievement/builtInRules.d.ts.map +1 -1
  43. package/dist/services/achievement/builtInRules.js +29 -10
  44. package/dist/services/achievement/eventTypeRequiresActor.d.ts +1 -0
  45. package/dist/services/achievement/eventTypeRequiresActor.d.ts.map +1 -1
  46. package/dist/services/achievement/eventTypeRequiresActor.js +2 -0
  47. package/dist/services/achievement/grantSideEffects.d.ts +11 -0
  48. package/dist/services/achievement/grantSideEffects.d.ts.map +1 -1
  49. package/dist/services/achievement/grantSideEffects.js +32 -0
  50. package/dist/services/achievement/index.d.ts +3 -1
  51. package/dist/services/achievement/index.d.ts.map +1 -1
  52. package/dist/services/achievement/index.js +2 -1
  53. package/dist/services/achievement/runReactions.d.ts +20 -0
  54. package/dist/services/achievement/runReactions.d.ts.map +1 -0
  55. package/dist/services/achievement/runReactions.js +86 -0
  56. package/dist/types.d.ts +46 -6
  57. package/dist/types.d.ts.map +1 -1
  58. package/package.json +1 -1
package/dist/catalog.d.ts CHANGED
@@ -22,4 +22,7 @@ export type EngineMetricSlug = (typeof ENGINE_METRICS)[number]['slug'];
22
22
  export declare const DEFAULT_ACHIEVEMENT_METRIC_SLUG: EngineMetricSlug;
23
23
  /** @deprecated Use {@link DEFAULT_ACHIEVEMENT_METRIC_SLUG}. */
24
24
  export declare const DEFAULT_ACHIEVEMENT_METRIC: "points";
25
+ /** Grant/revoke audit logs — progression already runs from Grants hooks. */
26
+ export declare const GRANT_AUDIT_EVENT_SLUGS: ReadonlySet<string>;
27
+ export declare function isGrantAuditEventSlug(slug: string | null | undefined): boolean;
25
28
  //# sourceMappingURL=catalog.d.ts.map
@@ -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;;;;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"}
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;AAEzE,4EAA4E;AAC5E,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAGtD,CAAA;AAEF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAE9E"}
package/dist/catalog.js CHANGED
@@ -8,3 +8,11 @@ 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;
11
+ /** Grant/revoke audit logs — progression already runs from Grants hooks. */
12
+ export const GRANT_AUDIT_EVENT_SLUGS = new Set([
13
+ 'achievement.granted',
14
+ 'achievement.revoked',
15
+ ]);
16
+ export function isGrantAuditEventSlug(slug) {
17
+ return typeof slug === 'string' && GRANT_AUDIT_EVENT_SLUGS.has(slug);
18
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"afterGrantMutation.d.ts","sourceRoot":"","sources":["../../../../src/collections/Grants/hooks/afterGrantMutation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAA;AAyBnF,eAAO,MAAM,gBAAgB,EAAE,yBAmB9B,CAAA;AAED,eAAO,MAAM,gBAAgB,EAAE,yBAmB9B,CAAA"}
1
+ {"version":3,"file":"afterGrantMutation.d.ts","sourceRoot":"","sources":["../../../../src/collections/Grants/hooks/afterGrantMutation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAA;AA0BnF,eAAO,MAAM,gBAAgB,EAAE,yBA2B9B,CAAA;AAED,eAAO,MAAM,gBAAgB,EAAE,yBA2B9B,CAAA"}
@@ -1,5 +1,6 @@
1
1
  import { CTX_CASCADING_REVOKE, CTX_SKIP_GRANT_SIDE_EFFECTS, runAfterGrantCreated, runAfterGrantDeleted } from '../../../services/achievement/grantSideEffects.js';
2
2
  import { relationId } from '../../../services/achievement/relationId.js';
3
+ import { runReactions } from '../../../services/achievement/runReactions.js';
3
4
  import { collectionOf } from '../../../collections/helpers.js';
4
5
  async function achievementSlug(req, achievementId) {
5
6
  try {
@@ -34,6 +35,13 @@ export const afterGrantChange = async ({ doc, operation, req }) => {
34
35
  scopeId,
35
36
  achievementSlug: await achievementSlug(req, achievementId),
36
37
  });
38
+ await runReactions({
39
+ req,
40
+ trigger: 'achievement.granted',
41
+ userId,
42
+ scopeId,
43
+ achievementId,
44
+ });
37
45
  return doc;
38
46
  };
39
47
  export const afterGrantDelete = async ({ doc, req }) => {
@@ -52,5 +60,12 @@ export const afterGrantDelete = async ({ doc, req }) => {
52
60
  achievementSlug: await achievementSlug(req, achievementId),
53
61
  cascading: Boolean(req.context?.[CTX_CASCADING_REVOKE]),
54
62
  });
63
+ await runReactions({
64
+ req,
65
+ trigger: 'achievement.revoked',
66
+ userId,
67
+ scopeId,
68
+ achievementId,
69
+ });
55
70
  return doc;
56
71
  };
@@ -0,0 +1,4 @@
1
+ import type { CollectionAfterChangeHook, CollectionAfterDeleteHook } from 'payload';
2
+ export declare const afterLogChange: CollectionAfterChangeHook;
3
+ export declare const afterLogDelete: CollectionAfterDeleteHook;
4
+ //# sourceMappingURL=afterLogMutation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"afterLogMutation.d.ts","sourceRoot":"","sources":["../../../../src/collections/Logs/hooks/afterLogMutation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAA;AA+CnF,eAAO,MAAM,cAAc,EAAE,yBAI5B,CAAA;AAED,eAAO,MAAM,cAAc,EAAE,yBAG5B,CAAA"}
@@ -0,0 +1,47 @@
1
+ import { CTX_SKIP_GRANT_SIDE_EFFECTS } from '../../../services/achievement/contextFlags.js';
2
+ import { getEventTypeFlags } from '../../../services/achievement/eventTypeRequiresActor.js';
3
+ import { syncProgressionFromLog } from '../../../services/achievement/grantSideEffects.js';
4
+ import { relationId } from '../../../services/achievement/relationId.js';
5
+ import { runReactions } from '../../../services/achievement/runReactions.js';
6
+ async function syncFromLogDoc(req, doc, operation) {
7
+ if (req.context?.[CTX_SKIP_GRANT_SIDE_EFFECTS])
8
+ return;
9
+ const userId = relationId(doc.user);
10
+ if (!userId)
11
+ return;
12
+ const flags = await getEventTypeFlags({
13
+ payload: req.payload,
14
+ req,
15
+ typeIdOrDoc: doc.type,
16
+ });
17
+ const scopeId = relationId(doc.scope);
18
+ const eventTypeId = relationId(doc.type);
19
+ await syncProgressionFromLog({
20
+ req,
21
+ userId,
22
+ scopeId,
23
+ eventTypeSlug: flags.slug,
24
+ operation,
25
+ });
26
+ if (operation === 'create') {
27
+ await runReactions({
28
+ req,
29
+ trigger: 'event',
30
+ userId,
31
+ scopeId,
32
+ eventTypeId,
33
+ eventTypeSlug: flags.slug,
34
+ log: doc,
35
+ });
36
+ }
37
+ }
38
+ export const afterLogChange = async ({ doc, operation, req }) => {
39
+ if (operation !== 'create')
40
+ return doc;
41
+ await syncFromLogDoc(req, doc, 'create');
42
+ return doc;
43
+ };
44
+ export const afterLogDelete = async ({ doc, req }) => {
45
+ await syncFromLogDoc(req, doc, 'delete');
46
+ return doc;
47
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/collections/Logs/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAI/C,eAAO,MAAM,KAAK,EAAE,gBAAgB,CAAC,OAAO,CAE3C,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/collections/Logs/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAK/C,eAAO,MAAM,KAAK,EAAE,gBAAgB,CAAC,OAAO,CAI3C,CAAA"}
@@ -1,4 +1,7 @@
1
1
  import { ensureTypeRequirements } from './ensureTypeRequirements.js';
2
+ import { afterLogChange, afterLogDelete } from './afterLogMutation.js';
2
3
  export const hooks = {
3
4
  beforeValidate: [ensureTypeRequirements],
5
+ afterChange: [afterLogChange],
6
+ afterDelete: [afterLogDelete],
4
7
  };
@@ -50,7 +50,7 @@ export function buildLogsCollection() {
50
50
  'change',
51
51
  'createdAt',
52
52
  ],
53
- description: 'Member activity history — grants, revokes, score changes, tier moves, and host custom events. Not a second grant store.',
53
+ description: 'Member activity history — grants, revokes, score changes, tier moves, and host custom events. Creating or deleting a host (or metric) log re-evaluates composed achievements and derived tiers.',
54
54
  }),
55
55
  fields: [
56
56
  ...optionalFields(scopeField()),
@@ -0,0 +1,12 @@
1
+ export declare const access: {
2
+ admin?: ({ req }: {
3
+ req: import("payload").PayloadRequest;
4
+ }) => boolean | Promise<boolean>;
5
+ create?: import("payload").Access;
6
+ delete?: import("payload").Access;
7
+ read?: import("payload").Access;
8
+ readVersions?: import("payload").Access;
9
+ unlock?: import("payload").Access;
10
+ update?: import("payload").Access;
11
+ };
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/collections/Reactions/access/index.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM;;;;;;;;;;CAAgC,CAAA"}
@@ -0,0 +1,2 @@
1
+ import { definitionAccess } from '../../access/definitions.js';
2
+ export const access = definitionAccess('reactions');
@@ -0,0 +1,3 @@
1
+ import type { CollectionConfig } from 'payload';
2
+ export declare function buildReactionsCollection(): CollectionConfig;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/collections/Reactions/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAS,MAAM,SAAS,CAAA;AAmBtD,wBAAgB,wBAAwB,IAAI,gBAAgB,CAoF3D"}
@@ -0,0 +1,97 @@
1
+ import { actionSelectOptions, BUILTIN_GRANT_ACTION, getHostActions } from '../../extensions/actions.js';
2
+ import { catalogFilterOptions } from '../fields/catalogFilter.js';
3
+ import { whenSiblingEquals } from '../fields/whenSibling.js';
4
+ import { collectionAdmin, collectionOf, columnsWithOptionalScope, optionalFields, slugOf } from '../helpers.js';
5
+ import { scopeField } from '../fields/index.js';
6
+ import { access } from './access/index.js';
7
+ function hostActionParamFields() {
8
+ const fields = [];
9
+ for (const action of getHostActions()) {
10
+ for (const field of action.fields ?? []) {
11
+ fields.push(whenSiblingEquals(field, 'action', action.type));
12
+ }
13
+ }
14
+ return fields;
15
+ }
16
+ export function buildReactionsCollection() {
17
+ return {
18
+ slug: slugOf('reactions'),
19
+ labels: {
20
+ singular: 'Achievement Reaction',
21
+ plural: 'Achievement Reactions',
22
+ },
23
+ access: { ...access },
24
+ admin: collectionAdmin({
25
+ useAsTitle: 'name',
26
+ defaultColumns: columnsWithOptionalScope(['name', 'trigger', 'action', 'enabled', 'scope']),
27
+ description: 'When an event is logged or an achievement is granted/revoked, run a set-based action. Re-running is safe — there is no run-history table.',
28
+ }),
29
+ fields: [
30
+ ...optionalFields(scopeField()),
31
+ {
32
+ name: 'name',
33
+ type: 'text',
34
+ required: true,
35
+ index: true,
36
+ admin: { description: 'Admin label for this reaction.' },
37
+ },
38
+ {
39
+ name: 'enabled',
40
+ type: 'checkbox',
41
+ defaultValue: true,
42
+ admin: { description: 'Turn off to keep the row without running it.' },
43
+ },
44
+ {
45
+ name: 'trigger',
46
+ type: 'select',
47
+ required: true,
48
+ options: [
49
+ { label: 'Event logged', value: 'event' },
50
+ { label: 'Achievement granted', value: 'achievement.granted' },
51
+ { label: 'Achievement revoked', value: 'achievement.revoked' },
52
+ ],
53
+ admin: {
54
+ description: 'Grant/revoke triggers fire from the grant row. Use “Event logged” for host event types (not achievement.granted / achievement.revoked — those already cascade from grants).',
55
+ },
56
+ },
57
+ {
58
+ name: 'eventType',
59
+ type: 'relationship',
60
+ relationTo: collectionOf('eventTypes'),
61
+ filterOptions: catalogFilterOptions,
62
+ admin: {
63
+ condition: (_, sibling) => sibling?.trigger === 'event',
64
+ description: 'Which log type starts this reaction.',
65
+ },
66
+ },
67
+ {
68
+ name: 'achievement',
69
+ type: 'relationship',
70
+ relationTo: collectionOf('achievements'),
71
+ filterOptions: catalogFilterOptions,
72
+ admin: {
73
+ condition: (_, sibling) => sibling?.trigger === 'achievement.granted' || sibling?.trigger === 'achievement.revoked',
74
+ description: 'Which achievement grant/revoke starts this reaction.',
75
+ },
76
+ },
77
+ {
78
+ name: 'action',
79
+ type: 'select',
80
+ required: true,
81
+ options: actionSelectOptions(),
82
+ admin: { description: 'Set-based command to run. Hosts register extra actions in plugin options.' },
83
+ },
84
+ {
85
+ name: 'targetAchievement',
86
+ type: 'relationship',
87
+ relationTo: collectionOf('achievements'),
88
+ filterOptions: catalogFilterOptions,
89
+ admin: {
90
+ condition: (_, sibling) => sibling?.action === BUILTIN_GRANT_ACTION,
91
+ description: 'Achievement to grant (no-ops if they already have it).',
92
+ },
93
+ },
94
+ ...hostActionParamFields(),
95
+ ],
96
+ };
97
+ }
@@ -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;AAgHpC;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,KAAK,EAAE,CAqB7C;AAED,mDAAmD;AACnD,wBAAgB,kBAAkB,IAAI,KAAK,EAAE,CAE5C"}
1
+ {"version":3,"file":"ruleFields.d.ts","sourceRoot":"","sources":["../../../src/collections/fields/ruleFields.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAU,MAAM,SAAS,CAAA;AAqI5C;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,KAAK,EAAE,CAqB7C;AAED,mDAAmD;AACnD,wBAAgB,kBAAkB,IAAI,KAAK,EAAE,CAE5C"}
@@ -1,5 +1,7 @@
1
+ import { getHostRuleTypeAdminEntries } from '../../extensions/registry.js';
1
2
  import { catalogFilterOptions } from './catalogFilter.js';
2
3
  import { collectionOf } from '../helpers.js';
4
+ import { whenSiblingEquals } from './whenSibling.js';
3
5
  function combinatorField(visibleWhenGroup) {
4
6
  return {
5
7
  name: 'combinator',
@@ -15,6 +17,21 @@ function combinatorField(visibleWhenGroup) {
15
17
  : {}),
16
18
  };
17
19
  }
20
+ function hostRuleTypeOptions() {
21
+ return getHostRuleTypeAdminEntries().map((rule) => ({
22
+ label: rule.label ?? rule.type,
23
+ value: rule.type,
24
+ }));
25
+ }
26
+ function hostRuleParamFields() {
27
+ const fields = [];
28
+ for (const rule of getHostRuleTypeAdminEntries()) {
29
+ for (const field of rule.fields ?? []) {
30
+ fields.push(whenSiblingEquals(field, 'type', rule.type));
31
+ }
32
+ }
33
+ return fields;
34
+ }
18
35
  function ruleTypeSelect(includeGroup) {
19
36
  return {
20
37
  name: 'type',
@@ -25,6 +42,7 @@ function ruleTypeSelect(includeGroup) {
25
42
  { label: 'Achievement complete', value: 'achievement-complete' },
26
43
  { label: 'Metric minimum', value: 'metric-minimum' },
27
44
  { label: 'Event count', value: 'event-count' },
45
+ ...hostRuleTypeOptions(),
28
46
  ...(includeGroup ? [{ label: 'Group', value: 'group' }] : []),
29
47
  ],
30
48
  };
@@ -97,6 +115,7 @@ function ruleParamFields() {
97
115
  description: 'Only count events whose actor held at least this tier in this scope when the event was written. Requires the event type to snapshot actor tiers. Leave empty to count every matching event.',
98
116
  },
99
117
  },
118
+ ...hostRuleParamFields(),
100
119
  ];
101
120
  }
102
121
  function buildRuleLeafFields() {
@@ -0,0 +1,7 @@
1
+ import type { Field } from 'payload';
2
+ /**
3
+ * AND an existing Admin `condition` with “sibling[key] === value”.
4
+ * Used so host rule/action fields only show for their `type` / `action`.
5
+ */
6
+ export declare function whenSiblingEquals(field: Field, key: string, value: string): Field;
7
+ //# sourceMappingURL=whenSibling.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whenSibling.d.ts","sourceRoot":"","sources":["../../../src/collections/fields/whenSibling.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAEpC;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAiBjF"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * AND an existing Admin `condition` with “sibling[key] === value”.
3
+ * Used so host rule/action fields only show for their `type` / `action`.
4
+ */
5
+ export function whenSiblingEquals(field, key, value) {
6
+ const admin = 'admin' in field && field.admin && typeof field.admin === 'object' ? field.admin : {};
7
+ const existing = 'condition' in admin && typeof admin.condition === 'function' ? admin.condition : undefined;
8
+ return {
9
+ ...field,
10
+ admin: {
11
+ ...admin,
12
+ condition: (data, siblingData, ctx) => {
13
+ if (siblingData?.[key] !== value)
14
+ return false;
15
+ if (!existing)
16
+ return true;
17
+ return Boolean(existing(data, siblingData, ctx));
18
+ },
19
+ },
20
+ };
21
+ }
@@ -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;AA2B/C,qEAAqE;AACrE,wBAAgB,2BAA2B,IAAI,gBAAgB,EAAE,CAMhE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/collections/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AA6B/C,qEAAqE;AACrE,wBAAgB,2BAA2B,IAAI,gBAAgB,EAAE,CAMhE"}
@@ -7,6 +7,7 @@ import { buildGrantsCollection } from './Grants/index.js';
7
7
  import { buildLogsCollection } from './Logs/index.js';
8
8
  import { buildMetricBalancesCollection } from './MetricBalances/index.js';
9
9
  import { buildMetricsCollection } from './Metrics/index.js';
10
+ import { buildReactionsCollection } from './Reactions/index.js';
10
11
  import { buildTierRequestsCollection } from './TierRequests/index.js';
11
12
  import { buildTiersCollection } from './Tiers/index.js';
12
13
  const builders = {
@@ -19,6 +20,7 @@ const builders = {
19
20
  achievementRequests: buildAchievementRequestsCollection,
20
21
  tierRequests: buildTierRequestsCollection,
21
22
  logs: buildLogsCollection,
23
+ reactions: buildReactionsCollection,
22
24
  };
23
25
  /** Build achievement collections after plugin options are stored. */
24
26
  export function buildAchievementCollections() {
@@ -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,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"}
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,CAWlF,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"}
@@ -19,6 +19,7 @@ export const DEFAULT_COLLECTION_BASE_SLUGS = {
19
19
  eventTypes: 'event-types',
20
20
  metrics: 'metrics',
21
21
  metricBalances: 'metric-balances',
22
+ reactions: 'reactions',
22
23
  };
23
24
  export const DEFAULT_ADMIN_GROUP = 'Achievements';
24
25
  /**
@@ -1,3 +1,4 @@
1
+ import type { Config } from 'payload';
1
2
  import type { AchievementPluginOptions } from './types.js';
2
3
  import { resolveCollectionSlugs } from './collections/slugs.js';
3
4
  export declare const DEFAULT_USERS_COLLECTION = "users";
@@ -23,8 +24,16 @@ export type ResolvedAchievementOptions = Omit<AchievementPluginOptions, 'users'
23
24
  reconcile: string | false;
24
25
  };
25
26
  };
26
- /** Unique, non-empty collection slugs from plugin `subjects.collections`. */
27
+ /**
28
+ * Unique, non-empty collection slugs from plugin `subjects.collections`.
29
+ * `'all'` is a plugin-wrap sentinel — returns `[]` until {@link resolveSubjectCollectionsFromConfig}.
30
+ */
27
31
  export declare function resolveSubjectCollections(options?: AchievementPluginOptions): string[];
32
+ /**
33
+ * Resolve log subject allowlist against the host Payload config.
34
+ * `'all'` = host collections except this plugin’s slugs and anything prefixed `payload-`.
35
+ */
36
+ export declare function resolveSubjectCollectionsFromConfig(options: AchievementPluginOptions | undefined, config: Pick<Config, 'collections'>): string[];
28
37
  export declare function resolveMeEndpointPath(me?: string | false): string | false;
29
38
  export declare function resolveLeaderboardEndpointPath(path?: string | false): string | false;
30
39
  export declare function resolveReconcileEndpointPath(path?: string | false): string | false;
@@ -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,iCAAiC,8BAA8B,CAAA;AAC5E,eAAO,MAAM,+BAA+B,4BAA4B,CAAA;AAExE,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAAC,wBAAwB,EAAE,OAAO,GAAG,WAAW,GAAG,UAAU,CAAC,GAAG;IAC5G,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,kFAAkF;IAClF,kBAAkB,EAAE,MAAM,EAAE,CAAA;IAC5B,+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;AAED,6EAA6E;AAC7E,wBAAgB,yBAAyB,CAAC,OAAO,CAAC,EAAE,wBAAwB,GAAG,MAAM,EAAE,CAWtF;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,CAwBjG"}
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAErC,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,GAAG,UAAU,CAAC,GAAG;IAC5G,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,kFAAkF;IAClF,kBAAkB,EAAE,MAAM,EAAE,CAAA;IAC5B,+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;AAkBD;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,CAAC,EAAE,wBAAwB,GAAG,MAAM,EAAE,CAItF;AAED;;;GAGG;AACH,wBAAgB,mCAAmC,CACjD,OAAO,EAAE,wBAAwB,GAAG,SAAS,EAC7C,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,GAClC,MAAM,EAAE,CAYV;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,CAwBjG"}
package/dist/defaults.js CHANGED
@@ -3,13 +3,11 @@ export const DEFAULT_USERS_COLLECTION = 'users';
3
3
  export const DEFAULT_ME_ENDPOINT_PATH = '/achievements/me';
4
4
  export const DEFAULT_LEADERBOARD_ENDPOINT_PATH = '/achievements/leaderboard';
5
5
  export const DEFAULT_RECONCILE_ENDPOINT_PATH = '/achievements/reconcile';
6
- /** Unique, non-empty collection slugs from plugin `subjects.collections`. */
7
- export function resolveSubjectCollections(options) {
8
- const raw = options?.subjects?.collections ?? [];
6
+ function uniqueSlugs(values) {
9
7
  const seen = new Set();
10
8
  const out = [];
11
- for (const slug of raw) {
12
- const trimmed = typeof slug === 'string' ? slug.trim() : '';
9
+ for (const value of values) {
10
+ const trimmed = value.trim();
13
11
  if (!trimmed || seen.has(trimmed))
14
12
  continue;
15
13
  seen.add(trimmed);
@@ -17,6 +15,37 @@ export function resolveSubjectCollections(options) {
17
15
  }
18
16
  return out;
19
17
  }
18
+ function isExcludedSubjectSlug(slug, pluginSlugs) {
19
+ return pluginSlugs.has(slug) || slug.startsWith('payload-');
20
+ }
21
+ /**
22
+ * Unique, non-empty collection slugs from plugin `subjects.collections`.
23
+ * `'all'` is a plugin-wrap sentinel — returns `[]` until {@link resolveSubjectCollectionsFromConfig}.
24
+ */
25
+ export function resolveSubjectCollections(options) {
26
+ const raw = options?.subjects?.collections;
27
+ if (raw == null || raw === 'all')
28
+ return [];
29
+ return uniqueSlugs(raw);
30
+ }
31
+ /**
32
+ * Resolve log subject allowlist against the host Payload config.
33
+ * `'all'` = host collections except this plugin’s slugs and anything prefixed `payload-`.
34
+ */
35
+ export function resolveSubjectCollectionsFromConfig(options, config) {
36
+ const raw = options?.subjects?.collections;
37
+ if (raw !== 'all')
38
+ return resolveSubjectCollections(options);
39
+ const pluginSlugs = new Set(Object.values(resolveCollectionSlugs(options)));
40
+ const fromHost = [];
41
+ for (const collection of config.collections ?? []) {
42
+ const slug = typeof collection.slug === 'string' ? collection.slug.trim() : '';
43
+ if (!slug || isExcludedSubjectSlug(slug, pluginSlugs))
44
+ continue;
45
+ fromHost.push(slug);
46
+ }
47
+ return uniqueSlugs(fromHost);
48
+ }
20
49
  function normalizeEndpointPath(path, fallback) {
21
50
  const trimmed = path.trim();
22
51
  if (!trimmed)
@@ -0,0 +1,8 @@
1
+ import type { Option } from 'payload';
2
+ import type { AchievementAction } from '../types.js';
3
+ export declare const BUILTIN_GRANT_ACTION = "achievement.grant";
4
+ /** Host actions whose `type` is not the built-in grant command. */
5
+ export declare function getHostActions(): AchievementAction[];
6
+ export declare function getHostAction(type: string): AchievementAction | null;
7
+ export declare function actionSelectOptions(): Option[];
8
+ //# sourceMappingURL=actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/extensions/actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAErC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAGpD,eAAO,MAAM,oBAAoB,sBAAsB,CAAA;AAEvD,mEAAmE;AACnE,wBAAgB,cAAc,IAAI,iBAAiB,EAAE,CASpD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAEpE;AAED,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAQ9C"}
@@ -0,0 +1,26 @@
1
+ import { getAchievementOptions } from '../options-store.js';
2
+ export const BUILTIN_GRANT_ACTION = 'achievement.grant';
3
+ /** Host actions whose `type` is not the built-in grant command. */
4
+ export function getHostActions() {
5
+ const out = [];
6
+ const seen = new Set([BUILTIN_GRANT_ACTION]);
7
+ for (const action of getAchievementOptions().extensions?.actions ?? []) {
8
+ if (!action.type || seen.has(action.type))
9
+ continue;
10
+ seen.add(action.type);
11
+ out.push(action);
12
+ }
13
+ return out;
14
+ }
15
+ export function getHostAction(type) {
16
+ return getHostActions().find((action) => action.type === type) ?? null;
17
+ }
18
+ export function actionSelectOptions() {
19
+ return [
20
+ { label: 'Grant achievement', value: BUILTIN_GRANT_ACTION },
21
+ ...getHostActions().map((action) => ({
22
+ label: action.label ?? action.type,
23
+ value: action.type,
24
+ })),
25
+ ];
26
+ }
@@ -1,3 +1,5 @@
1
1
  import type { AchievementRuleType } from '../types.js';
2
2
  export declare function getRuleTypeMap(): Map<string, AchievementRuleType>;
3
+ /** Host rule types that can appear in the Admin type select (skips built-in keys). */
4
+ export declare function getHostRuleTypeAdminEntries(): AchievementRuleType[];
3
5
  //# sourceMappingURL=registry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/extensions/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAItD,wBAAgB,cAAc,IAAI,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CASjE"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/extensions/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAYtD,wBAAgB,cAAc,IAAI,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CASjE;AAED,sFAAsF;AACtF,wBAAgB,2BAA2B,IAAI,mBAAmB,EAAE,CASnE"}
@@ -1,5 +1,12 @@
1
1
  import { getAchievementOptions } from '../options-store.js';
2
2
  import { builtInRuleTypes } from '../services/achievement/builtInRules.js';
3
+ const BUILTIN_RULE_SELECT_TYPES = new Set([
4
+ 'tier-at-least',
5
+ 'achievement-complete',
6
+ 'metric-minimum',
7
+ 'event-count',
8
+ 'group',
9
+ ]);
3
10
  export function getRuleTypeMap() {
4
11
  const map = new Map();
5
12
  for (const rule of builtInRuleTypes) {
@@ -10,3 +17,15 @@ export function getRuleTypeMap() {
10
17
  }
11
18
  return map;
12
19
  }
20
+ /** Host rule types that can appear in the Admin type select (skips built-in keys). */
21
+ export function getHostRuleTypeAdminEntries() {
22
+ const out = [];
23
+ const seen = new Set();
24
+ for (const rule of getAchievementOptions().extensions?.ruleTypes ?? []) {
25
+ if (!rule.type || BUILTIN_RULE_SELECT_TYPES.has(rule.type) || seen.has(rule.type))
26
+ continue;
27
+ seen.add(rule.type);
28
+ out.push(rule);
29
+ }
30
+ return out;
31
+ }
package/dist/index.d.ts CHANGED
@@ -1,13 +1,13 @@
1
- export { DEFAULT_ACHIEVEMENT_METRIC, DEFAULT_ACHIEVEMENT_METRIC_SLUG, ENGINE_EVENT_TYPES, ENGINE_METRICS, } from './catalog.js';
1
+ export { DEFAULT_ACHIEVEMENT_METRIC, DEFAULT_ACHIEVEMENT_METRIC_SLUG, ENGINE_EVENT_TYPES, ENGINE_METRICS, GRANT_AUDIT_EVENT_SLUGS, isGrantAuditEventSlug, } from './catalog.js';
2
2
  export type { EngineEventTypeSlug, EngineMetricSlug } from './catalog.js';
3
3
  export { achievementPlugin } from './plugin.js';
4
4
  export { seedAchievementCatalog, seedAchievements } from './seed/index.js';
5
5
  export type { AchievementSeedAchievement, AchievementSeedCatalogRow, AchievementSeedInput, AchievementSeedLocalizedText, AchievementSeedTier, } from './seed/index.js';
6
- export { evaluateRules, evaluateRuleProgress, collectAchievementCompleteRefs, buildCatalogProgressGroups, buildUnlockRequirementLeaves, getUserProgress, loadUserProgressReviews, getMetricLeaderboard, grantAchievement, loadMetricDoc, recordEvent, recordLog, recordMetricChange, rebuildMetricBalance, rebuildMetricBalancesForUser, reconcileProgression, reconcileUserProgression, releasePendingAchievementReviews, releasePendingTierReviews, resolveCurrentTier, resolveElapsedAnchor, resolveMetricValue, resolveTierProgress, reviewAchievementRequest, submitAchievementRequest, syncTierChangedLog, syncTierProgression, syncCompositeProgression, catalogRef, transitionLogData, transitionToId, logSubject, readLogSubject, validateRuleGroup, validateRuleNode, } from './services/achievement/index.js';
6
+ export { evaluateRules, evaluateRuleProgress, collectAchievementCompleteRefs, buildCatalogProgressGroups, buildUnlockRequirementLeaves, getUserProgress, loadUserProgressReviews, getMetricLeaderboard, grantAchievement, loadMetricDoc, recordEvent, recordLog, recordMetricChange, rebuildMetricBalance, rebuildMetricBalancesForUser, reconcileProgression, reconcileUserProgression, releasePendingAchievementReviews, releasePendingTierReviews, resolveCurrentTier, resolveElapsedAnchor, resolveMetricValue, resolveTierProgress, reviewAchievementRequest, submitAchievementRequest, syncTierChangedLog, syncTierProgression, syncCompositeProgression, syncProgressionFromLog, runReactions, catalogRef, transitionLogData, transitionToId, logSubject, readLogSubject, validateRuleGroup, validateRuleNode, } from './services/achievement/index.js';
7
7
  export type { ResolvedTier, RuleGroup, TierLadderProgress, CatalogProgressGroup, CatalogProgressItem, UnlockRequirementLeaf, UnlockRequirementRelation, GetUserProgressInclude, UserProgressMeResponse, UserProgressReviews, UserProgressTierRequest, CatalogRef, TransitionLogData, LogSubjectRef, MetricLeaderboardResult, MetricLeaderboardRow, ReconcileProgressionArgs, ReconcileProgressionResult, ReleaseReviewGateResult, } from './services/achievement/index.js';
8
- export type { BuiltInEventType, BuiltInRuleType, AchievementCollectionKey, AchievementCollectionOverride, AchievementCollectionsOptions, AchievementEndpointsOptions, AchievementMetricAnchor, AchievementMetricAnchorConfig, AchievementMetricAnchorEntry, AchievementPluginOptions, AchievementRuleType, AchievementScopeConfig, AchievementSubjectsOptions, AchievementUsersOptions, } from './types.js';
8
+ export type { BuiltInEventType, BuiltInRuleType, AchievementCollectionKey, AchievementCollectionOverride, AchievementCollectionsOptions, AchievementEndpointsOptions, AchievementMetricAnchor, AchievementMetricAnchorConfig, AchievementMetricAnchorEntry, AchievementPluginOptions, AchievementRuleType, AchievementAction, AchievementActionRunArgs, AchievementReactionTrigger, AchievementScopeConfig, AchievementSubjectsOptions, AchievementUsersOptions, } from './types.js';
9
9
  export { DEFAULT_COLLECTION_BASE_SLUGS, DEFAULT_COLLECTION_PREFIX, DEFAULT_ADMIN_GROUP } from './collections/slugs.js';
10
- export { DEFAULT_ME_ENDPOINT_PATH, DEFAULT_LEADERBOARD_ENDPOINT_PATH, DEFAULT_RECONCILE_ENDPOINT_PATH, resolveSubjectCollections, } from './defaults.js';
10
+ export { DEFAULT_ME_ENDPOINT_PATH, DEFAULT_LEADERBOARD_ENDPOINT_PATH, DEFAULT_RECONCILE_ENDPOINT_PATH, resolveSubjectCollections, resolveSubjectCollectionsFromConfig, } from './defaults.js';
11
11
  export { collectionOf, slugOf } from './collections/helpers.js';
12
12
  export { eachRuleLeaf } from './collections/hooks/eachRuleLeaf.js';
13
13
  export { isAchievementPluginEnabled } from './enabled.js';
@@ -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,cAAc,CAAA;AACrB,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAC1E,YAAY,EACV,0BAA0B,EAC1B,yBAAyB,EACzB,oBAAoB,EACpB,4BAA4B,EAC5B,mBAAmB,GACpB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,8BAA8B,EAC9B,0BAA0B,EAC1B,4BAA4B,EAC5B,eAAe,EACf,uBAAuB,EACvB,oBAAoB,EACpB,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,SAAS,EACT,kBAAkB,EAClB,oBAAoB,EACpB,4BAA4B,EAC5B,oBAAoB,EACpB,wBAAwB,EACxB,gCAAgC,EAChC,yBAAyB,EACzB,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,wBAAwB,EACxB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,iCAAiC,CAAA;AACxC,YAAY,EACV,YAAY,EACZ,SAAS,EACT,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,EACzB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,uBAAuB,EACvB,UAAU,EACV,iBAAiB,EACjB,aAAa,EACb,uBAAuB,EACvB,oBAAoB,EACpB,wBAAwB,EACxB,0BAA0B,EAC1B,uBAAuB,GACxB,MAAM,iCAAiC,CAAA;AACxC,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,wBAAwB,EACxB,6BAA6B,EAC7B,6BAA6B,EAC7B,2BAA2B,EAC3B,uBAAuB,EACvB,6BAA6B,EAC7B,4BAA4B,EAC5B,wBAAwB,EACxB,mBAAmB,EACnB,sBAAsB,EACtB,0BAA0B,EAC1B,uBAAuB,GACxB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,6BAA6B,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AACtH,OAAO,EACL,wBAAwB,EACxB,iCAAiC,EACjC,+BAA+B,EAC/B,yBAAyB,GAC1B,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAA;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAA;AAClE,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAA;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAA;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,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,EACd,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,cAAc,CAAA;AACrB,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAC1E,YAAY,EACV,0BAA0B,EAC1B,yBAAyB,EACzB,oBAAoB,EACpB,4BAA4B,EAC5B,mBAAmB,GACpB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,8BAA8B,EAC9B,0BAA0B,EAC1B,4BAA4B,EAC5B,eAAe,EACf,uBAAuB,EACvB,oBAAoB,EACpB,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,SAAS,EACT,kBAAkB,EAClB,oBAAoB,EACpB,4BAA4B,EAC5B,oBAAoB,EACpB,wBAAwB,EACxB,gCAAgC,EAChC,yBAAyB,EACzB,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,wBAAwB,EACxB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,sBAAsB,EACtB,YAAY,EACZ,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,iCAAiC,CAAA;AACxC,YAAY,EACV,YAAY,EACZ,SAAS,EACT,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,EACzB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,uBAAuB,EACvB,UAAU,EACV,iBAAiB,EACjB,aAAa,EACb,uBAAuB,EACvB,oBAAoB,EACpB,wBAAwB,EACxB,0BAA0B,EAC1B,uBAAuB,GACxB,MAAM,iCAAiC,CAAA;AACxC,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,wBAAwB,EACxB,6BAA6B,EAC7B,6BAA6B,EAC7B,2BAA2B,EAC3B,uBAAuB,EACvB,6BAA6B,EAC7B,4BAA4B,EAC5B,wBAAwB,EACxB,mBAAmB,EACnB,iBAAiB,EACjB,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,EACtB,0BAA0B,EAC1B,uBAAuB,GACxB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,6BAA6B,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AACtH,OAAO,EACL,wBAAwB,EACxB,iCAAiC,EACjC,+BAA+B,EAC/B,yBAAyB,EACzB,mCAAmC,GACpC,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAA;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAA;AAClE,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAA;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAA;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA"}
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
- export { DEFAULT_ACHIEVEMENT_METRIC, DEFAULT_ACHIEVEMENT_METRIC_SLUG, ENGINE_EVENT_TYPES, ENGINE_METRICS, } from './catalog.js';
1
+ export { DEFAULT_ACHIEVEMENT_METRIC, DEFAULT_ACHIEVEMENT_METRIC_SLUG, ENGINE_EVENT_TYPES, ENGINE_METRICS, GRANT_AUDIT_EVENT_SLUGS, isGrantAuditEventSlug, } from './catalog.js';
2
2
  export { achievementPlugin } from './plugin.js';
3
3
  export { seedAchievementCatalog, seedAchievements } from './seed/index.js';
4
- export { evaluateRules, evaluateRuleProgress, collectAchievementCompleteRefs, buildCatalogProgressGroups, buildUnlockRequirementLeaves, getUserProgress, loadUserProgressReviews, getMetricLeaderboard, grantAchievement, loadMetricDoc, recordEvent, recordLog, recordMetricChange, rebuildMetricBalance, rebuildMetricBalancesForUser, reconcileProgression, reconcileUserProgression, releasePendingAchievementReviews, releasePendingTierReviews, resolveCurrentTier, resolveElapsedAnchor, resolveMetricValue, resolveTierProgress, reviewAchievementRequest, submitAchievementRequest, syncTierChangedLog, syncTierProgression, syncCompositeProgression, catalogRef, transitionLogData, transitionToId, logSubject, readLogSubject, validateRuleGroup, validateRuleNode, } from './services/achievement/index.js';
4
+ export { evaluateRules, evaluateRuleProgress, collectAchievementCompleteRefs, buildCatalogProgressGroups, buildUnlockRequirementLeaves, getUserProgress, loadUserProgressReviews, getMetricLeaderboard, grantAchievement, loadMetricDoc, recordEvent, recordLog, recordMetricChange, rebuildMetricBalance, rebuildMetricBalancesForUser, reconcileProgression, reconcileUserProgression, releasePendingAchievementReviews, releasePendingTierReviews, resolveCurrentTier, resolveElapsedAnchor, resolveMetricValue, resolveTierProgress, reviewAchievementRequest, submitAchievementRequest, syncTierChangedLog, syncTierProgression, syncCompositeProgression, syncProgressionFromLog, runReactions, catalogRef, transitionLogData, transitionToId, logSubject, readLogSubject, validateRuleGroup, validateRuleNode, } from './services/achievement/index.js';
5
5
  export { DEFAULT_COLLECTION_BASE_SLUGS, DEFAULT_COLLECTION_PREFIX, DEFAULT_ADMIN_GROUP } from './collections/slugs.js';
6
- export { DEFAULT_ME_ENDPOINT_PATH, DEFAULT_LEADERBOARD_ENDPOINT_PATH, DEFAULT_RECONCILE_ENDPOINT_PATH, resolveSubjectCollections, } from './defaults.js';
6
+ export { DEFAULT_ME_ENDPOINT_PATH, DEFAULT_LEADERBOARD_ENDPOINT_PATH, DEFAULT_RECONCILE_ENDPOINT_PATH, resolveSubjectCollections, resolveSubjectCollectionsFromConfig, } from './defaults.js';
7
7
  export { collectionOf, slugOf } from './collections/helpers.js';
8
8
  export { eachRuleLeaf } from './collections/hooks/eachRuleLeaf.js';
9
9
  export { isAchievementPluginEnabled } from './enabled.js';