@brandlift/payload-loggs 1.1.0 → 1.3.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.
@@ -1,7 +1,7 @@
1
1
  import type { CollectionConfig } from 'payload';
2
2
  export type SiteActivityLogData = {
3
3
  title: string;
4
- operation: 'create' | 'update' | 'delete' | 'login' | 'logout';
4
+ operation: 'create' | 'update' | 'delete' | 'login' | 'logout' | 'publish' | 'unpublish' | 'draft_saved';
5
5
  resourceName?: string;
6
6
  resourceType: 'collection' | 'global';
7
7
  collectionLabel?: string;
@@ -48,6 +48,18 @@ export const SiteActivityCollection = {
48
48
  label: 'Delete',
49
49
  value: 'delete'
50
50
  },
51
+ {
52
+ label: 'Publish',
53
+ value: 'publish'
54
+ },
55
+ {
56
+ label: 'Unpublish',
57
+ value: 'unpublish'
58
+ },
59
+ {
60
+ label: 'Draft Saved',
61
+ value: 'draft_saved'
62
+ },
51
63
  {
52
64
  label: 'Login',
53
65
  value: 'login'
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/collections/SiteActivityCollection.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload';\n\nexport type SiteActivityLogData = {\n title: string;\n operation: 'create' | 'update' | 'delete' | 'login' | 'logout';\n resourceName?: string;\n resourceType: 'collection' | 'global';\n collectionLabel?: string;\n slug: string;\n documentId?: string;\n locale?: string;\n user?: string | number;\n userEmail?: string;\n userDisplay?: string;\n createdAt?: string;\n};\n\nexport const SITE_ACTIVITY_SLUG = 'site-activity';\n\nexport const SiteActivityCollection: CollectionConfig = {\n slug: SITE_ACTIVITY_SLUG,\n labels: {\n plural: 'Site Activities',\n singular: 'Site Activity',\n },\n admin: {\n defaultColumns: ['title', 'operation', 'resourceName', 'collectionLabel', 'userDisplay', 'createdAt'],\n useAsTitle: 'title',\n },\n access: {\n read: ({ req }) => Boolean(req.user),\n create: () => false,\n update: () => false,\n delete: () => false,\n },\n fields: [\n {\n name: 'title',\n type: 'text',\n required: true,\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'operation',\n type: 'select',\n required: true,\n options: [\n { label: 'Create', value: 'create' },\n { label: 'Update', value: 'update' },\n { label: 'Delete', value: 'delete' },\n { label: 'Login', value: 'login' },\n { label: 'Logout', value: 'logout' },\n ],\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'resourceName',\n type: 'text',\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'resourceType',\n type: 'select',\n required: true,\n options: [\n { label: 'Collection', value: 'collection' },\n { label: 'Global', value: 'global' },\n ],\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'collectionLabel',\n type: 'text',\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'slug',\n type: 'text',\n required: true,\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'documentId',\n type: 'text',\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'locale',\n type: 'text',\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'user',\n type: 'relationship',\n relationTo: 'users',\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'userEmail',\n type: 'text',\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'userDisplay',\n type: 'text',\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'createdAt',\n type: 'date',\n admin: {\n readOnly: true,\n },\n defaultValue: () => new Date().toISOString(),\n required: true,\n },\n ],\n timestamps: false,\n};\n\nexport default SiteActivityCollection;\n"],"names":["SITE_ACTIVITY_SLUG","SiteActivityCollection","slug","labels","plural","singular","admin","defaultColumns","useAsTitle","access","read","req","Boolean","user","create","update","delete","fields","name","type","required","readOnly","options","label","value","relationTo","defaultValue","Date","toISOString","timestamps"],"mappings":"AAiBA,OAAO,MAAMA,qBAAqB,gBAAgB;AAElD,OAAO,MAAMC,yBAA2C;IACtDC,MAAMF;IACNG,QAAQ;QACNC,QAAQ;QACRC,UAAU;IACZ;IACAC,OAAO;QACLC,gBAAgB;YAAC;YAAS;YAAa;YAAgB;YAAmB;YAAe;SAAY;QACrGC,YAAY;IACd;IACAC,QAAQ;QACNC,MAAM,CAAC,EAAEC,GAAG,EAAE,GAAKC,QAAQD,IAAIE,IAAI;QACnCC,QAAQ,IAAM;QACdC,QAAQ,IAAM;QACdC,QAAQ,IAAM;IAChB;IACAC,QAAQ;QACN;YACEC,MAAM;YACNC,MAAM;YACNC,UAAU;YACVd,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,UAAU;YACVE,SAAS;gBACP;oBAAEC,OAAO;oBAAUC,OAAO;gBAAS;gBACnC;oBAAED,OAAO;oBAAUC,OAAO;gBAAS;gBACnC;oBAAED,OAAO;oBAAUC,OAAO;gBAAS;gBACnC;oBAAED,OAAO;oBAASC,OAAO;gBAAQ;gBACjC;oBAAED,OAAO;oBAAUC,OAAO;gBAAS;aACpC;YACDlB,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNb,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,UAAU;YACVE,SAAS;gBACP;oBAAEC,OAAO;oBAAcC,OAAO;gBAAa;gBAC3C;oBAAED,OAAO;oBAAUC,OAAO;gBAAS;aACpC;YACDlB,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNb,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,UAAU;YACVd,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNb,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNb,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNM,YAAY;YACZnB,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNb,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNb,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNb,OAAO;gBACLe,UAAU;YACZ;YACAK,cAAc,IAAM,IAAIC,OAAOC,WAAW;YAC1CR,UAAU;QACZ;KACD;IACDS,YAAY;AACd,EAAE;AAEF,eAAe5B,uBAAuB"}
1
+ {"version":3,"sources":["../../src/collections/SiteActivityCollection.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload';\n\nexport type SiteActivityLogData = {\n title: string;\n operation: 'create' | 'update' | 'delete' | 'login' | 'logout' | 'publish' | 'unpublish' | 'draft_saved';\n resourceName?: string;\n resourceType: 'collection' | 'global';\n collectionLabel?: string;\n slug: string;\n documentId?: string;\n locale?: string;\n user?: string | number;\n userEmail?: string;\n userDisplay?: string;\n createdAt?: string;\n};\n\nexport const SITE_ACTIVITY_SLUG = 'site-activity';\n\nexport const SiteActivityCollection: CollectionConfig = {\n slug: SITE_ACTIVITY_SLUG,\n labels: {\n plural: 'Site Activities',\n singular: 'Site Activity',\n },\n admin: {\n defaultColumns: ['title', 'operation', 'resourceName', 'collectionLabel', 'userDisplay', 'createdAt'],\n useAsTitle: 'title',\n },\n access: {\n read: ({ req }) => Boolean(req.user),\n create: () => false,\n update: () => false,\n delete: () => false,\n },\n fields: [\n {\n name: 'title',\n type: 'text',\n required: true,\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'operation',\n type: 'select',\n required: true,\n options: [\n { label: 'Create', value: 'create' },\n { label: 'Update', value: 'update' },\n { label: 'Delete', value: 'delete' },\n { label: 'Publish', value: 'publish' },\n { label: 'Unpublish', value: 'unpublish' },\n { label: 'Draft Saved', value: 'draft_saved' },\n { label: 'Login', value: 'login' },\n { label: 'Logout', value: 'logout' },\n ],\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'resourceName',\n type: 'text',\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'resourceType',\n type: 'select',\n required: true,\n options: [\n { label: 'Collection', value: 'collection' },\n { label: 'Global', value: 'global' },\n ],\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'collectionLabel',\n type: 'text',\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'slug',\n type: 'text',\n required: true,\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'documentId',\n type: 'text',\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'locale',\n type: 'text',\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'user',\n type: 'relationship',\n relationTo: 'users',\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'userEmail',\n type: 'text',\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'userDisplay',\n type: 'text',\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'createdAt',\n type: 'date',\n admin: {\n readOnly: true,\n },\n defaultValue: () => new Date().toISOString(),\n required: true,\n },\n ],\n timestamps: false,\n};\n\nexport default SiteActivityCollection;\n"],"names":["SITE_ACTIVITY_SLUG","SiteActivityCollection","slug","labels","plural","singular","admin","defaultColumns","useAsTitle","access","read","req","Boolean","user","create","update","delete","fields","name","type","required","readOnly","options","label","value","relationTo","defaultValue","Date","toISOString","timestamps"],"mappings":"AAiBA,OAAO,MAAMA,qBAAqB,gBAAgB;AAElD,OAAO,MAAMC,yBAA2C;IACtDC,MAAMF;IACNG,QAAQ;QACNC,QAAQ;QACRC,UAAU;IACZ;IACAC,OAAO;QACLC,gBAAgB;YAAC;YAAS;YAAa;YAAgB;YAAmB;YAAe;SAAY;QACrGC,YAAY;IACd;IACAC,QAAQ;QACNC,MAAM,CAAC,EAAEC,GAAG,EAAE,GAAKC,QAAQD,IAAIE,IAAI;QACnCC,QAAQ,IAAM;QACdC,QAAQ,IAAM;QACdC,QAAQ,IAAM;IAChB;IACAC,QAAQ;QACN;YACEC,MAAM;YACNC,MAAM;YACNC,UAAU;YACVd,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,UAAU;YACVE,SAAS;gBACP;oBAAEC,OAAO;oBAAUC,OAAO;gBAAS;gBACnC;oBAAED,OAAO;oBAAUC,OAAO;gBAAS;gBACnC;oBAAED,OAAO;oBAAUC,OAAO;gBAAS;gBACnC;oBAAED,OAAO;oBAAWC,OAAO;gBAAU;gBACrC;oBAAED,OAAO;oBAAaC,OAAO;gBAAY;gBACzC;oBAAED,OAAO;oBAAeC,OAAO;gBAAc;gBAC7C;oBAAED,OAAO;oBAASC,OAAO;gBAAQ;gBACjC;oBAAED,OAAO;oBAAUC,OAAO;gBAAS;aACpC;YACDlB,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNb,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,UAAU;YACVE,SAAS;gBACP;oBAAEC,OAAO;oBAAcC,OAAO;gBAAa;gBAC3C;oBAAED,OAAO;oBAAUC,OAAO;gBAAS;aACpC;YACDlB,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNb,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNC,UAAU;YACVd,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNb,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNb,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNM,YAAY;YACZnB,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNb,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNb,OAAO;gBACLe,UAAU;YACZ;QACF;QACA;YACEH,MAAM;YACNC,MAAM;YACNb,OAAO;gBACLe,UAAU;YACZ;YACAK,cAAc,IAAM,IAAIC,OAAOC,WAAW;YAC1CR,UAAU;QACZ;KACD;IACDS,YAAY;AACd,EAAE;AAEF,eAAe5B,uBAAuB"}
@@ -1,17 +1,34 @@
1
+ import { ActivityEvent } from '../types/events.js';
1
2
  import { getResourceTitle } from '../pluginUtils/getResourceTitle.js';
2
3
  import { formatUserDisplay } from '../pluginUtils/formatUserDisplay.js';
3
4
  import { getCollectionLabel } from '../pluginUtils/getCollectionLabel.js';
4
5
  import { SITE_ACTIVITY_SLUG } from '../collections/SiteActivityCollection.js';
6
+ import { getActivityLabel, getCollectionActivityDetails } from '../pluginUtils/getActivityDetails.js';
7
+ function isDuplicateEvent(req, collectionSlug, docId, eventKey) {
8
+ if (!req || !req.context) {
9
+ return false;
10
+ }
11
+ const loggedEvents = req.context._loggedActivityEvents || new Set();
12
+ const fullKey = `${collectionSlug}:${docId}:${eventKey}`;
13
+ if (loggedEvents.has(fullKey)) {
14
+ return true;
15
+ }
16
+ loggedEvents.add(fullKey);
17
+ req.context._loggedActivityEvents = loggedEvents;
18
+ return false;
19
+ }
5
20
  export const createCollectionAfterChangeHook = (collection, payloadConfig, _pluginConfig)=>{
6
21
  return async ({ doc, previousDoc, operation, req })=>{
7
22
  if (!req || req.context?.skipLogs || req.context?.skipAuditorLogs) {
8
23
  return doc;
9
24
  }
10
25
  try {
11
- const isCreate = operation === 'create' || !previousDoc;
12
- const opType = isCreate ? 'create' : 'update';
26
+ const { event, title, operation: opType } = getCollectionActivityDetails(collection, operation, doc, previousDoc, req);
27
+ const docId = doc?.id ? String(doc.id) : 'new';
28
+ if (isDuplicateEvent(req, collection.slug, docId, event)) {
29
+ return doc;
30
+ }
13
31
  const label = getCollectionLabel(collection);
14
- const title = isCreate ? `${label} created` : `${label} modified`;
15
32
  const resourceName = getResourceTitle(doc, doc?.id);
16
33
  const isLocalizationEnabled = Boolean(payloadConfig.localization);
17
34
  const locale = isLocalizationEnabled ? req.locale : undefined;
@@ -61,8 +78,12 @@ export const createCollectionAfterDeleteHook = (collection, payloadConfig, _plug
61
78
  return doc;
62
79
  }
63
80
  try {
81
+ const docId = id ? String(id) : 'unknown';
82
+ if (isDuplicateEvent(req, collection.slug, docId, ActivityEvent.DELETED)) {
83
+ return doc;
84
+ }
64
85
  const label = getCollectionLabel(collection);
65
- const title = `${label} deleted`;
86
+ const title = getActivityLabel(ActivityEvent.DELETED, label);
66
87
  const resourceName = getResourceTitle(doc, id);
67
88
  const isLocalizationEnabled = Boolean(payloadConfig.localization);
68
89
  const locale = isLocalizationEnabled ? req.locale : undefined;
@@ -78,7 +99,7 @@ export const createCollectionAfterDeleteHook = (collection, payloadConfig, _plug
78
99
  resourceType: 'collection',
79
100
  collectionLabel: label,
80
101
  slug: collection.slug,
81
- documentId: id ? String(id) : undefined,
102
+ documentId: docId !== 'unknown' ? docId : undefined,
82
103
  ...locale ? {
83
104
  locale
84
105
  } : {},
@@ -112,10 +133,14 @@ export const createCollectionAfterLoginHook = (collection, _payloadConfig, _plug
112
133
  return user;
113
134
  }
114
135
  try {
136
+ const userId = user?.id ? String(user.id) : 'user';
137
+ if (isDuplicateEvent(req, collection.slug, userId, ActivityEvent.USER_LOGIN)) {
138
+ return user;
139
+ }
115
140
  const label = getCollectionLabel(collection);
116
141
  const userEmail = user?.email || req.user?.email;
117
142
  const userDisplay = formatUserDisplay(userEmail);
118
- const title = userDisplay ? `User ${userDisplay} logged in` : `${label} logged in`;
143
+ const title = getActivityLabel(ActivityEvent.USER_LOGIN, label);
119
144
  await req.payload.create({
120
145
  collection: SITE_ACTIVITY_SLUG,
121
146
  data: {
@@ -156,10 +181,14 @@ export const createCollectionAfterLogoutHook = (collection, _payloadConfig, _plu
156
181
  return;
157
182
  }
158
183
  try {
184
+ const userId = req.user?.id ? String(req.user.id) : 'user';
185
+ if (isDuplicateEvent(req, collection.slug, userId, ActivityEvent.USER_LOGOUT)) {
186
+ return;
187
+ }
159
188
  const label = getCollectionLabel(collection);
160
189
  const userEmail = req.user?.email;
161
190
  const userDisplay = formatUserDisplay(userEmail);
162
- const title = userDisplay ? `User ${userDisplay} logged out` : `${label} logged out`;
191
+ const title = getActivityLabel(ActivityEvent.USER_LOGOUT, label);
163
192
  await req.payload.create({
164
193
  collection: SITE_ACTIVITY_SLUG,
165
194
  data: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/collectionHooks.ts"],"sourcesContent":["import type { CollectionAfterChangeHook, CollectionAfterDeleteHook, CollectionAfterLoginHook, CollectionAfterLogoutHook, CollectionConfig, Config } from 'payload';\n\nimport type { PluginConfig } from '../types/config.js';\nimport { getResourceTitle } from '../pluginUtils/getResourceTitle.js';\nimport { formatUserDisplay } from '../pluginUtils/formatUserDisplay.js';\nimport { getCollectionLabel } from '../pluginUtils/getCollectionLabel.js';\nimport { SITE_ACTIVITY_SLUG } from '../collections/SiteActivityCollection.js';\n\nexport const createCollectionAfterChangeHook = (\n collection: CollectionConfig,\n payloadConfig: Config,\n _pluginConfig?: PluginConfig,\n): CollectionAfterChangeHook => {\n return async ({ doc, previousDoc, operation, req }) => {\n if (!req || req.context?.skipLogs || req.context?.skipAuditorLogs) {\n return doc;\n }\n\n try {\n const isCreate = operation === 'create' || !previousDoc;\n const opType = isCreate ? 'create' : 'update';\n const label = getCollectionLabel(collection);\n const title = isCreate ? `${label} created` : `${label} modified`;\n\n const resourceName = getResourceTitle(doc, doc?.id);\n const isLocalizationEnabled = Boolean(payloadConfig.localization);\n const locale = isLocalizationEnabled ? req.locale : undefined;\n\n const userEmail = req.user?.email || (doc && typeof doc === 'object' && 'email' in doc && typeof doc.email === 'string' ? doc.email : undefined);\n const userDisplay = formatUserDisplay(userEmail);\n const userId = req.user?.id || (doc && typeof doc === 'object' && 'id' in doc ? doc.id : undefined);\n\n await req.payload.create({\n collection: SITE_ACTIVITY_SLUG,\n data: {\n title,\n operation: opType,\n resourceName,\n resourceType: 'collection',\n collectionLabel: label,\n slug: collection.slug,\n documentId: doc?.id ? String(doc.id) : undefined,\n ...(locale ? { locale } : {}),\n ...(userId !== undefined && userId !== null ? { user: userId } : {}),\n ...(userEmail ? { userEmail } : {}),\n ...(userDisplay ? { userDisplay } : {}),\n },\n req,\n overrideAccess: true,\n context: {\n ...req.context,\n skipLogs: true,\n skipAuditorLogs: true,\n },\n });\n }\n catch (error) {\n req.payload?.logger?.error?.(`[payload-loggs] Error logging collection afterChange for ${collection.slug}: ${error}`);\n }\n\n return doc;\n };\n};\n\nexport const createCollectionAfterDeleteHook = (\n collection: CollectionConfig,\n payloadConfig: Config,\n _pluginConfig?: PluginConfig,\n): CollectionAfterDeleteHook => {\n return async ({ doc, id, req }) => {\n if (!req || req.context?.skipLogs || req.context?.skipAuditorLogs) {\n return doc;\n }\n\n try {\n const label = getCollectionLabel(collection);\n const title = `${label} deleted`;\n\n const resourceName = getResourceTitle(doc, id);\n const isLocalizationEnabled = Boolean(payloadConfig.localization);\n const locale = isLocalizationEnabled ? req.locale : undefined;\n\n const userEmail = req.user?.email || (doc && typeof doc === 'object' && 'email' in doc && typeof doc.email === 'string' ? doc.email : undefined);\n const userDisplay = formatUserDisplay(userEmail);\n const userId = req.user?.id || (doc && typeof doc === 'object' && 'id' in doc ? doc.id : undefined);\n\n await req.payload.create({\n collection: SITE_ACTIVITY_SLUG,\n data: {\n title,\n operation: 'delete',\n resourceName,\n resourceType: 'collection',\n collectionLabel: label,\n slug: collection.slug,\n documentId: id ? String(id) : undefined,\n ...(locale ? { locale } : {}),\n ...(userId !== undefined && userId !== null ? { user: userId } : {}),\n ...(userEmail ? { userEmail } : {}),\n ...(userDisplay ? { userDisplay } : {}),\n },\n req,\n overrideAccess: true,\n context: {\n ...req.context,\n skipLogs: true,\n skipAuditorLogs: true,\n },\n });\n }\n catch (error) {\n req.payload?.logger?.error?.(`[payload-loggs] Error logging collection afterDelete for ${collection.slug}: ${error}`);\n }\n\n return doc;\n };\n};\n\nexport const createCollectionAfterLoginHook = (\n collection: CollectionConfig,\n _payloadConfig: Config,\n _pluginConfig?: PluginConfig,\n): CollectionAfterLoginHook => {\n return async ({ user, req }) => {\n if (!req || req.context?.skipLogs || req.context?.skipAuditorLogs) {\n return user;\n }\n\n try {\n const label = getCollectionLabel(collection);\n const userEmail = user?.email || req.user?.email;\n const userDisplay = formatUserDisplay(userEmail);\n const title = userDisplay ? `User ${userDisplay} logged in` : `${label} logged in`;\n\n await req.payload.create({\n collection: SITE_ACTIVITY_SLUG,\n data: {\n title,\n operation: 'login',\n resourceName: userEmail || String(user?.id || 'User'),\n resourceType: 'collection',\n collectionLabel: label,\n slug: collection.slug,\n documentId: user?.id ? String(user.id) : undefined,\n ...(user?.id !== undefined && user?.id !== null ? { user: user.id } : {}),\n ...(userEmail ? { userEmail } : {}),\n ...(userDisplay ? { userDisplay } : {}),\n },\n req,\n overrideAccess: true,\n context: {\n ...req.context,\n skipLogs: true,\n skipAuditorLogs: true,\n },\n });\n }\n catch (error) {\n req.payload?.logger?.error?.(`[payload-loggs] Error logging afterLogin for ${collection.slug}: ${error}`);\n }\n\n return user;\n };\n};\n\nexport const createCollectionAfterLogoutHook = (\n collection: CollectionConfig,\n _payloadConfig: Config,\n _pluginConfig?: PluginConfig,\n): CollectionAfterLogoutHook => {\n return async ({ req }) => {\n if (!req || req.context?.skipLogs || req.context?.skipAuditorLogs) {\n return;\n }\n\n try {\n const label = getCollectionLabel(collection);\n const userEmail = req.user?.email;\n const userDisplay = formatUserDisplay(userEmail);\n const title = userDisplay ? `User ${userDisplay} logged out` : `${label} logged out`;\n\n await req.payload.create({\n collection: SITE_ACTIVITY_SLUG,\n data: {\n title,\n operation: 'logout',\n resourceName: userEmail || String(req.user?.id || 'User'),\n resourceType: 'collection',\n collectionLabel: label,\n slug: collection.slug,\n documentId: req.user?.id ? String(req.user.id) : undefined,\n ...(req.user?.id !== undefined && req.user?.id !== null ? { user: req.user.id } : {}),\n ...(userEmail ? { userEmail } : {}),\n ...(userDisplay ? { userDisplay } : {}),\n },\n req,\n overrideAccess: true,\n context: {\n ...req.context,\n skipLogs: true,\n skipAuditorLogs: true,\n },\n });\n }\n catch (error) {\n req.payload?.logger?.error?.(`[payload-loggs] Error logging afterLogout for ${collection.slug}: ${error}`);\n }\n };\n};\n"],"names":["getResourceTitle","formatUserDisplay","getCollectionLabel","SITE_ACTIVITY_SLUG","createCollectionAfterChangeHook","collection","payloadConfig","_pluginConfig","doc","previousDoc","operation","req","context","skipLogs","skipAuditorLogs","isCreate","opType","label","title","resourceName","id","isLocalizationEnabled","Boolean","localization","locale","undefined","userEmail","user","email","userDisplay","userId","payload","create","data","resourceType","collectionLabel","slug","documentId","String","overrideAccess","error","logger","createCollectionAfterDeleteHook","createCollectionAfterLoginHook","_payloadConfig","createCollectionAfterLogoutHook"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/hooks/collectionHooks.ts"],"sourcesContent":["import type { CollectionAfterChangeHook, CollectionAfterDeleteHook, CollectionAfterLoginHook, CollectionAfterLogoutHook, CollectionConfig, Config } from 'payload';\n\nimport { ActivityEvent } from '../types/events.js';\nimport type { PluginConfig } from '../types/config.js';\nimport { getResourceTitle } from '../pluginUtils/getResourceTitle.js';\nimport { formatUserDisplay } from '../pluginUtils/formatUserDisplay.js';\nimport { getCollectionLabel } from '../pluginUtils/getCollectionLabel.js';\nimport { SITE_ACTIVITY_SLUG } from '../collections/SiteActivityCollection.js';\nimport { getActivityLabel, getCollectionActivityDetails } from '../pluginUtils/getActivityDetails.js';\n\nfunction isDuplicateEvent(req: any, collectionSlug: string, docId: string, eventKey: string): boolean {\n if (!req || !req.context) {\n return false;\n }\n\n const loggedEvents: Set<string> = (req.context._loggedActivityEvents as Set<string>) || new Set<string>();\n const fullKey = `${collectionSlug}:${docId}:${eventKey}`;\n\n if (loggedEvents.has(fullKey)) {\n return true;\n }\n\n loggedEvents.add(fullKey);\n req.context._loggedActivityEvents = loggedEvents;\n return false;\n}\n\nexport const createCollectionAfterChangeHook = (\n collection: CollectionConfig,\n payloadConfig: Config,\n _pluginConfig?: PluginConfig,\n): CollectionAfterChangeHook => {\n return async ({ doc, previousDoc, operation, req }) => {\n if (!req || req.context?.skipLogs || req.context?.skipAuditorLogs) {\n return doc;\n }\n\n try {\n const { event, title, operation: opType } = getCollectionActivityDetails(\n collection,\n operation as 'create' | 'update',\n doc as Record<string, unknown>,\n previousDoc as Record<string, unknown> | undefined,\n req,\n );\n\n const docId = doc?.id ? String(doc.id) : 'new';\n if (isDuplicateEvent(req, collection.slug, docId, event)) {\n return doc;\n }\n\n const label = getCollectionLabel(collection);\n const resourceName = getResourceTitle(doc, doc?.id);\n const isLocalizationEnabled = Boolean(payloadConfig.localization);\n const locale = isLocalizationEnabled ? req.locale : undefined;\n\n const userEmail = req.user?.email || (doc && typeof doc === 'object' && 'email' in doc && typeof doc.email === 'string' ? doc.email : undefined);\n const userDisplay = formatUserDisplay(userEmail);\n const userId = req.user?.id || (doc && typeof doc === 'object' && 'id' in doc ? doc.id : undefined);\n\n await req.payload.create({\n collection: SITE_ACTIVITY_SLUG,\n data: {\n title,\n operation: opType,\n resourceName,\n resourceType: 'collection',\n collectionLabel: label,\n slug: collection.slug,\n documentId: doc?.id ? String(doc.id) : undefined,\n ...(locale ? { locale } : {}),\n ...(userId !== undefined && userId !== null ? { user: userId } : {}),\n ...(userEmail ? { userEmail } : {}),\n ...(userDisplay ? { userDisplay } : {}),\n },\n req,\n overrideAccess: true,\n context: {\n ...req.context,\n skipLogs: true,\n skipAuditorLogs: true,\n },\n });\n }\n catch (error) {\n req.payload?.logger?.error?.(`[payload-loggs] Error logging collection afterChange for ${collection.slug}: ${error}`);\n }\n\n return doc;\n };\n};\n\nexport const createCollectionAfterDeleteHook = (\n collection: CollectionConfig,\n payloadConfig: Config,\n _pluginConfig?: PluginConfig,\n): CollectionAfterDeleteHook => {\n return async ({ doc, id, req }) => {\n if (!req || req.context?.skipLogs || req.context?.skipAuditorLogs) {\n return doc;\n }\n\n try {\n const docId = id ? String(id) : 'unknown';\n if (isDuplicateEvent(req, collection.slug, docId, ActivityEvent.DELETED)) {\n return doc;\n }\n\n const label = getCollectionLabel(collection);\n const title = getActivityLabel(ActivityEvent.DELETED, label);\n\n const resourceName = getResourceTitle(doc, id);\n const isLocalizationEnabled = Boolean(payloadConfig.localization);\n const locale = isLocalizationEnabled ? req.locale : undefined;\n\n const userEmail = req.user?.email || (doc && typeof doc === 'object' && 'email' in doc && typeof doc.email === 'string' ? doc.email : undefined);\n const userDisplay = formatUserDisplay(userEmail);\n const userId = req.user?.id || (doc && typeof doc === 'object' && 'id' in doc ? doc.id : undefined);\n\n await req.payload.create({\n collection: SITE_ACTIVITY_SLUG,\n data: {\n title,\n operation: 'delete',\n resourceName,\n resourceType: 'collection',\n collectionLabel: label,\n slug: collection.slug,\n documentId: docId !== 'unknown' ? docId : undefined,\n ...(locale ? { locale } : {}),\n ...(userId !== undefined && userId !== null ? { user: userId } : {}),\n ...(userEmail ? { userEmail } : {}),\n ...(userDisplay ? { userDisplay } : {}),\n },\n req,\n overrideAccess: true,\n context: {\n ...req.context,\n skipLogs: true,\n skipAuditorLogs: true,\n },\n });\n }\n catch (error) {\n req.payload?.logger?.error?.(`[payload-loggs] Error logging collection afterDelete for ${collection.slug}: ${error}`);\n }\n\n return doc;\n };\n};\n\nexport const createCollectionAfterLoginHook = (\n collection: CollectionConfig,\n _payloadConfig: Config,\n _pluginConfig?: PluginConfig,\n): CollectionAfterLoginHook => {\n return async ({ user, req }) => {\n if (!req || req.context?.skipLogs || req.context?.skipAuditorLogs) {\n return user;\n }\n\n try {\n const userId = user?.id ? String(user.id) : 'user';\n if (isDuplicateEvent(req, collection.slug, userId, ActivityEvent.USER_LOGIN)) {\n return user;\n }\n\n const label = getCollectionLabel(collection);\n const userEmail = user?.email || req.user?.email;\n const userDisplay = formatUserDisplay(userEmail);\n const title = getActivityLabel(ActivityEvent.USER_LOGIN, label);\n\n await req.payload.create({\n collection: SITE_ACTIVITY_SLUG,\n data: {\n title,\n operation: 'login',\n resourceName: userEmail || String(user?.id || 'User'),\n resourceType: 'collection',\n collectionLabel: label,\n slug: collection.slug,\n documentId: user?.id ? String(user.id) : undefined,\n ...(user?.id !== undefined && user?.id !== null ? { user: user.id } : {}),\n ...(userEmail ? { userEmail } : {}),\n ...(userDisplay ? { userDisplay } : {}),\n },\n req,\n overrideAccess: true,\n context: {\n ...req.context,\n skipLogs: true,\n skipAuditorLogs: true,\n },\n });\n }\n catch (error) {\n req.payload?.logger?.error?.(`[payload-loggs] Error logging afterLogin for ${collection.slug}: ${error}`);\n }\n\n return user;\n };\n};\n\nexport const createCollectionAfterLogoutHook = (\n collection: CollectionConfig,\n _payloadConfig: Config,\n _pluginConfig?: PluginConfig,\n): CollectionAfterLogoutHook => {\n return async ({ req }) => {\n if (!req || req.context?.skipLogs || req.context?.skipAuditorLogs) {\n return;\n }\n\n try {\n const userId = req.user?.id ? String(req.user.id) : 'user';\n if (isDuplicateEvent(req, collection.slug, userId, ActivityEvent.USER_LOGOUT)) {\n return;\n }\n\n const label = getCollectionLabel(collection);\n const userEmail = req.user?.email;\n const userDisplay = formatUserDisplay(userEmail);\n const title = getActivityLabel(ActivityEvent.USER_LOGOUT, label);\n\n await req.payload.create({\n collection: SITE_ACTIVITY_SLUG,\n data: {\n title,\n operation: 'logout',\n resourceName: userEmail || String(req.user?.id || 'User'),\n resourceType: 'collection',\n collectionLabel: label,\n slug: collection.slug,\n documentId: req.user?.id ? String(req.user.id) : undefined,\n ...(req.user?.id !== undefined && req.user?.id !== null ? { user: req.user.id } : {}),\n ...(userEmail ? { userEmail } : {}),\n ...(userDisplay ? { userDisplay } : {}),\n },\n req,\n overrideAccess: true,\n context: {\n ...req.context,\n skipLogs: true,\n skipAuditorLogs: true,\n },\n });\n }\n catch (error) {\n req.payload?.logger?.error?.(`[payload-loggs] Error logging afterLogout for ${collection.slug}: ${error}`);\n }\n };\n};\n"],"names":["ActivityEvent","getResourceTitle","formatUserDisplay","getCollectionLabel","SITE_ACTIVITY_SLUG","getActivityLabel","getCollectionActivityDetails","isDuplicateEvent","req","collectionSlug","docId","eventKey","context","loggedEvents","_loggedActivityEvents","Set","fullKey","has","add","createCollectionAfterChangeHook","collection","payloadConfig","_pluginConfig","doc","previousDoc","operation","skipLogs","skipAuditorLogs","event","title","opType","id","String","slug","label","resourceName","isLocalizationEnabled","Boolean","localization","locale","undefined","userEmail","user","email","userDisplay","userId","payload","create","data","resourceType","collectionLabel","documentId","overrideAccess","error","logger","createCollectionAfterDeleteHook","DELETED","createCollectionAfterLoginHook","_payloadConfig","USER_LOGIN","createCollectionAfterLogoutHook","USER_LOGOUT"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -2,14 +2,31 @@ import { getResourceTitle } from '../pluginUtils/getResourceTitle.js';
2
2
  import { formatUserDisplay } from '../pluginUtils/formatUserDisplay.js';
3
3
  import { getCollectionLabel } from '../pluginUtils/getCollectionLabel.js';
4
4
  import { SITE_ACTIVITY_SLUG } from '../collections/SiteActivityCollection.js';
5
+ import { getGlobalActivityDetails } from '../pluginUtils/getActivityDetails.js';
6
+ function isDuplicateEvent(req, globalSlug, eventKey) {
7
+ if (!req || !req.context) {
8
+ return false;
9
+ }
10
+ const loggedEvents = req.context._loggedActivityEvents || new Set();
11
+ const fullKey = `global:${globalSlug}:${eventKey}`;
12
+ if (loggedEvents.has(fullKey)) {
13
+ return true;
14
+ }
15
+ loggedEvents.add(fullKey);
16
+ req.context._loggedActivityEvents = loggedEvents;
17
+ return false;
18
+ }
5
19
  export const createGlobalAfterChangeHook = (globalConfig, payloadConfig, _pluginConfig)=>{
6
- return async ({ doc, req })=>{
20
+ return async ({ doc, previousDoc, req })=>{
7
21
  if (!req || req.context?.skipLogs || req.context?.skipAuditorLogs) {
8
22
  return doc;
9
23
  }
10
24
  try {
25
+ const { event, title, operation: opType } = getGlobalActivityDetails(globalConfig, doc, previousDoc, req);
26
+ if (isDuplicateEvent(req, globalConfig.slug, event)) {
27
+ return doc;
28
+ }
11
29
  const label = getCollectionLabel(globalConfig);
12
- const title = `Global ${label} updated`;
13
30
  const resourceName = getResourceTitle(doc) || label;
14
31
  const isLocalizationEnabled = Boolean(payloadConfig.localization);
15
32
  const locale = isLocalizationEnabled ? req.locale : undefined;
@@ -20,7 +37,7 @@ export const createGlobalAfterChangeHook = (globalConfig, payloadConfig, _plugin
20
37
  collection: SITE_ACTIVITY_SLUG,
21
38
  data: {
22
39
  title,
23
- operation: 'update',
40
+ operation: opType,
24
41
  resourceName,
25
42
  resourceType: 'global',
26
43
  collectionLabel: label,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/globalHooks.ts"],"sourcesContent":["import type { Config, GlobalAfterChangeHook, GlobalConfig } from 'payload';\n\nimport type { PluginConfig } from '../types/config.js';\nimport { getResourceTitle } from '../pluginUtils/getResourceTitle.js';\nimport { formatUserDisplay } from '../pluginUtils/formatUserDisplay.js';\nimport { getCollectionLabel } from '../pluginUtils/getCollectionLabel.js';\nimport { SITE_ACTIVITY_SLUG } from '../collections/SiteActivityCollection.js';\n\nexport const createGlobalAfterChangeHook = (\n globalConfig: GlobalConfig,\n payloadConfig: Config,\n _pluginConfig?: PluginConfig,\n): GlobalAfterChangeHook => {\n return async ({ doc, req }) => {\n if (!req || req.context?.skipLogs || req.context?.skipAuditorLogs) {\n return doc;\n }\n\n try {\n const label = getCollectionLabel(globalConfig);\n const title = `Global ${label} updated`;\n\n const resourceName = getResourceTitle(doc) || label;\n const isLocalizationEnabled = Boolean(payloadConfig.localization);\n const locale = isLocalizationEnabled ? req.locale : undefined;\n\n const userEmail = req.user?.email;\n const userDisplay = formatUserDisplay(userEmail);\n const userId = req.user?.id;\n\n await req.payload.create({\n collection: SITE_ACTIVITY_SLUG,\n data: {\n title,\n operation: 'update',\n resourceName,\n resourceType: 'global',\n collectionLabel: label,\n slug: globalConfig.slug,\n ...(locale ? { locale } : {}),\n ...(userId !== undefined && userId !== null ? { user: userId } : {}),\n ...(userEmail ? { userEmail } : {}),\n ...(userDisplay ? { userDisplay } : {}),\n },\n req,\n overrideAccess: true,\n context: {\n ...req.context,\n skipLogs: true,\n skipAuditorLogs: true,\n },\n });\n }\n catch (error) {\n req.payload?.logger?.error?.(`[payload-loggs] Error logging global afterChange for ${globalConfig.slug}: ${error}`);\n }\n\n return doc;\n };\n};\n"],"names":["getResourceTitle","formatUserDisplay","getCollectionLabel","SITE_ACTIVITY_SLUG","createGlobalAfterChangeHook","globalConfig","payloadConfig","_pluginConfig","doc","req","context","skipLogs","skipAuditorLogs","label","title","resourceName","isLocalizationEnabled","Boolean","localization","locale","undefined","userEmail","user","email","userDisplay","userId","id","payload","create","collection","data","operation","resourceType","collectionLabel","slug","overrideAccess","error","logger"],"mappings":"AAGA,SAASA,gBAAgB,QAAQ,qCAAqC;AACtE,SAASC,iBAAiB,QAAQ,sCAAsC;AACxE,SAASC,kBAAkB,QAAQ,uCAAuC;AAC1E,SAASC,kBAAkB,QAAQ,2CAA2C;AAE9E,OAAO,MAAMC,8BAA8B,CACzCC,cACAC,eACAC;IAEA,OAAO,OAAO,EAAEC,GAAG,EAAEC,GAAG,EAAE;QACxB,IAAI,CAACA,OAAOA,IAAIC,OAAO,EAAEC,YAAYF,IAAIC,OAAO,EAAEE,iBAAiB;YACjE,OAAOJ;QACT;QAEA,IAAI;YACF,MAAMK,QAAQX,mBAAmBG;YACjC,MAAMS,QAAQ,CAAC,OAAO,EAAED,MAAM,QAAQ,CAAC;YAEvC,MAAME,eAAef,iBAAiBQ,QAAQK;YAC9C,MAAMG,wBAAwBC,QAAQX,cAAcY,YAAY;YAChE,MAAMC,SAASH,wBAAwBP,IAAIU,MAAM,GAAGC;YAEpD,MAAMC,YAAYZ,IAAIa,IAAI,EAAEC;YAC5B,MAAMC,cAAcvB,kBAAkBoB;YACtC,MAAMI,SAAShB,IAAIa,IAAI,EAAEI;YAEzB,MAAMjB,IAAIkB,OAAO,CAACC,MAAM,CAAC;gBACvBC,YAAY1B;gBACZ2B,MAAM;oBACJhB;oBACAiB,WAAW;oBACXhB;oBACAiB,cAAc;oBACdC,iBAAiBpB;oBACjBqB,MAAM7B,aAAa6B,IAAI;oBACvB,GAAIf,SAAS;wBAAEA;oBAAO,IAAI,CAAC,CAAC;oBAC5B,GAAIM,WAAWL,aAAaK,WAAW,OAAO;wBAAEH,MAAMG;oBAAO,IAAI,CAAC,CAAC;oBACnE,GAAIJ,YAAY;wBAAEA;oBAAU,IAAI,CAAC,CAAC;oBAClC,GAAIG,cAAc;wBAAEA;oBAAY,IAAI,CAAC,CAAC;gBACxC;gBACAf;gBACA0B,gBAAgB;gBAChBzB,SAAS;oBACP,GAAGD,IAAIC,OAAO;oBACdC,UAAU;oBACVC,iBAAiB;gBACnB;YACF;QACF,EACA,OAAOwB,OAAO;YACZ3B,IAAIkB,OAAO,EAAEU,QAAQD,QAAQ,CAAC,qDAAqD,EAAE/B,aAAa6B,IAAI,CAAC,EAAE,EAAEE,OAAO;QACpH;QAEA,OAAO5B;IACT;AACF,EAAE"}
1
+ {"version":3,"sources":["../../src/hooks/globalHooks.ts"],"sourcesContent":["import type { Config, GlobalAfterChangeHook, GlobalConfig } from 'payload';\n\nimport type { PluginConfig } from '../types/config.js';\nimport { getResourceTitle } from '../pluginUtils/getResourceTitle.js';\nimport { formatUserDisplay } from '../pluginUtils/formatUserDisplay.js';\nimport { getCollectionLabel } from '../pluginUtils/getCollectionLabel.js';\nimport { SITE_ACTIVITY_SLUG } from '../collections/SiteActivityCollection.js';\nimport { getGlobalActivityDetails } from '../pluginUtils/getActivityDetails.js';\n\nfunction isDuplicateEvent(req: any, globalSlug: string, eventKey: string): boolean {\n if (!req || !req.context) {\n return false;\n }\n\n const loggedEvents: Set<string> = (req.context._loggedActivityEvents as Set<string>) || new Set<string>();\n const fullKey = `global:${globalSlug}:${eventKey}`;\n\n if (loggedEvents.has(fullKey)) {\n return true;\n }\n\n loggedEvents.add(fullKey);\n req.context._loggedActivityEvents = loggedEvents;\n return false;\n}\n\nexport const createGlobalAfterChangeHook = (\n globalConfig: GlobalConfig,\n payloadConfig: Config,\n _pluginConfig?: PluginConfig,\n): GlobalAfterChangeHook => {\n return async ({ doc, previousDoc, req }: { doc: Record<string, unknown>; previousDoc?: Record<string, unknown>; req?: any }) => {\n if (!req || req.context?.skipLogs || req.context?.skipAuditorLogs) {\n return doc;\n }\n\n try {\n const { event, title, operation: opType } = getGlobalActivityDetails(\n globalConfig,\n doc as Record<string, unknown>,\n previousDoc as Record<string, unknown> | undefined,\n req,\n );\n\n if (isDuplicateEvent(req, globalConfig.slug, event)) {\n return doc;\n }\n\n const label = getCollectionLabel(globalConfig);\n const resourceName = getResourceTitle(doc) || label;\n const isLocalizationEnabled = Boolean(payloadConfig.localization);\n const locale = isLocalizationEnabled ? req.locale : undefined;\n\n const userEmail = req.user?.email;\n const userDisplay = formatUserDisplay(userEmail);\n const userId = req.user?.id;\n\n await req.payload.create({\n collection: SITE_ACTIVITY_SLUG,\n data: {\n title,\n operation: opType,\n resourceName,\n resourceType: 'global',\n collectionLabel: label,\n slug: globalConfig.slug,\n ...(locale ? { locale } : {}),\n ...(userId !== undefined && userId !== null ? { user: userId } : {}),\n ...(userEmail ? { userEmail } : {}),\n ...(userDisplay ? { userDisplay } : {}),\n },\n req,\n overrideAccess: true,\n context: {\n ...req.context,\n skipLogs: true,\n skipAuditorLogs: true,\n },\n });\n }\n catch (error) {\n req.payload?.logger?.error?.(`[payload-loggs] Error logging global afterChange for ${globalConfig.slug}: ${error}`);\n }\n\n return doc;\n };\n};\n"],"names":["getResourceTitle","formatUserDisplay","getCollectionLabel","SITE_ACTIVITY_SLUG","getGlobalActivityDetails","isDuplicateEvent","req","globalSlug","eventKey","context","loggedEvents","_loggedActivityEvents","Set","fullKey","has","add","createGlobalAfterChangeHook","globalConfig","payloadConfig","_pluginConfig","doc","previousDoc","skipLogs","skipAuditorLogs","event","title","operation","opType","slug","label","resourceName","isLocalizationEnabled","Boolean","localization","locale","undefined","userEmail","user","email","userDisplay","userId","id","payload","create","collection","data","resourceType","collectionLabel","overrideAccess","error","logger"],"mappings":"AAGA,SAASA,gBAAgB,QAAQ,qCAAqC;AACtE,SAASC,iBAAiB,QAAQ,sCAAsC;AACxE,SAASC,kBAAkB,QAAQ,uCAAuC;AAC1E,SAASC,kBAAkB,QAAQ,2CAA2C;AAC9E,SAASC,wBAAwB,QAAQ,uCAAuC;AAEhF,SAASC,iBAAiBC,GAAQ,EAAEC,UAAkB,EAAEC,QAAgB;IACtE,IAAI,CAACF,OAAO,CAACA,IAAIG,OAAO,EAAE;QACxB,OAAO;IACT;IAEA,MAAMC,eAA4B,AAACJ,IAAIG,OAAO,CAACE,qBAAqB,IAAoB,IAAIC;IAC5F,MAAMC,UAAU,CAAC,OAAO,EAAEN,WAAW,CAAC,EAAEC,UAAU;IAElD,IAAIE,aAAaI,GAAG,CAACD,UAAU;QAC7B,OAAO;IACT;IAEAH,aAAaK,GAAG,CAACF;IACjBP,IAAIG,OAAO,CAACE,qBAAqB,GAAGD;IACpC,OAAO;AACT;AAEA,OAAO,MAAMM,8BAA8B,CACzCC,cACAC,eACAC;IAEA,OAAO,OAAO,EAAEC,GAAG,EAAEC,WAAW,EAAEf,GAAG,EAAsF;QACzH,IAAI,CAACA,OAAOA,IAAIG,OAAO,EAAEa,YAAYhB,IAAIG,OAAO,EAAEc,iBAAiB;YACjE,OAAOH;QACT;QAEA,IAAI;YACF,MAAM,EAAEI,KAAK,EAAEC,KAAK,EAAEC,WAAWC,MAAM,EAAE,GAAGvB,yBAC1Ca,cACAG,KACAC,aACAf;YAGF,IAAID,iBAAiBC,KAAKW,aAAaW,IAAI,EAAEJ,QAAQ;gBACnD,OAAOJ;YACT;YAEA,MAAMS,QAAQ3B,mBAAmBe;YACjC,MAAMa,eAAe9B,iBAAiBoB,QAAQS;YAC9C,MAAME,wBAAwBC,QAAQd,cAAce,YAAY;YAChE,MAAMC,SAASH,wBAAwBzB,IAAI4B,MAAM,GAAGC;YAEpD,MAAMC,YAAY9B,IAAI+B,IAAI,EAAEC;YAC5B,MAAMC,cAActC,kBAAkBmC;YACtC,MAAMI,SAASlC,IAAI+B,IAAI,EAAEI;YAEzB,MAAMnC,IAAIoC,OAAO,CAACC,MAAM,CAAC;gBACvBC,YAAYzC;gBACZ0C,MAAM;oBACJpB;oBACAC,WAAWC;oBACXG;oBACAgB,cAAc;oBACdC,iBAAiBlB;oBACjBD,MAAMX,aAAaW,IAAI;oBACvB,GAAIM,SAAS;wBAAEA;oBAAO,IAAI,CAAC,CAAC;oBAC5B,GAAIM,WAAWL,aAAaK,WAAW,OAAO;wBAAEH,MAAMG;oBAAO,IAAI,CAAC,CAAC;oBACnE,GAAIJ,YAAY;wBAAEA;oBAAU,IAAI,CAAC,CAAC;oBAClC,GAAIG,cAAc;wBAAEA;oBAAY,IAAI,CAAC,CAAC;gBACxC;gBACAjC;gBACA0C,gBAAgB;gBAChBvC,SAAS;oBACP,GAAGH,IAAIG,OAAO;oBACda,UAAU;oBACVC,iBAAiB;gBACnB;YACF;QACF,EACA,OAAO0B,OAAO;YACZ3C,IAAIoC,OAAO,EAAEQ,QAAQD,QAAQ,CAAC,qDAAqD,EAAEhC,aAAaW,IAAI,CAAC,EAAE,EAAEqB,OAAO;QACpH;QAEA,OAAO7B;IACT;AACF,EAAE"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { ActivityEvent } from './types/events.js';
1
2
  import { getResourceTitle } from './pluginUtils/getResourceTitle.js';
2
3
  import type { SiteActivityLog } from './collections/siteActivity.js';
3
4
  import { formatUserDisplay } from './pluginUtils/formatUserDisplay.js';
@@ -5,8 +6,10 @@ import { getCollectionLabel } from './pluginUtils/getCollectionLabel.js';
5
6
  import { payloadLoggsPlugin, siteActivity, siteActivityPlugin } from './plugin.js';
6
7
  import { siteActivity as siteActivityCollection } from './collections/siteActivity.js';
7
8
  import { SITE_ACTIVITY_SLUG, SiteActivityCollection } from './collections/SiteActivityCollection.js';
9
+ import { getActivityEvent, getActivityLabel, getCollectionActivityDetails, getGlobalActivityDetails } from './pluginUtils/getActivityDetails.js';
8
10
  export type { SiteActivityLogData } from './collections/SiteActivityCollection.js';
9
11
  export type { AutomationConfig, PluginConfig } from './types/config.js';
12
+ export type { ActivityClassificationParams, ActivityDetails } from './types/events.js';
10
13
  export type { SiteActivityLog };
11
- export { formatUserDisplay, getCollectionLabel, getResourceTitle, payloadLoggsPlugin, SITE_ACTIVITY_SLUG, siteActivity, SiteActivityCollection, siteActivityCollection, siteActivityPlugin, };
14
+ export { ActivityEvent, formatUserDisplay, getActivityEvent, getActivityLabel, getCollectionActivityDetails, getCollectionLabel, getGlobalActivityDetails, getResourceTitle, payloadLoggsPlugin, SITE_ACTIVITY_SLUG, siteActivity, SiteActivityCollection, siteActivityCollection, siteActivityPlugin, };
12
15
  export default siteActivity;
package/dist/index.js CHANGED
@@ -1,10 +1,12 @@
1
+ import { ActivityEvent } from './types/events.js';
1
2
  import { getResourceTitle } from './pluginUtils/getResourceTitle.js';
2
3
  import { formatUserDisplay } from './pluginUtils/formatUserDisplay.js';
3
4
  import { getCollectionLabel } from './pluginUtils/getCollectionLabel.js';
4
5
  import { payloadLoggsPlugin, siteActivity, siteActivityPlugin } from './plugin.js';
5
6
  import { siteActivity as siteActivityCollection } from './collections/siteActivity.js';
6
7
  import { SITE_ACTIVITY_SLUG, SiteActivityCollection } from './collections/SiteActivityCollection.js';
7
- export { formatUserDisplay, getCollectionLabel, getResourceTitle, payloadLoggsPlugin, SITE_ACTIVITY_SLUG, siteActivity, SiteActivityCollection, siteActivityCollection, siteActivityPlugin };
8
+ import { getActivityEvent, getActivityLabel, getCollectionActivityDetails, getGlobalActivityDetails } from './pluginUtils/getActivityDetails.js';
9
+ export { ActivityEvent, formatUserDisplay, getActivityEvent, getActivityLabel, getCollectionActivityDetails, getCollectionLabel, getGlobalActivityDetails, getResourceTitle, payloadLoggsPlugin, SITE_ACTIVITY_SLUG, siteActivity, SiteActivityCollection, siteActivityCollection, siteActivityPlugin };
8
10
  export default siteActivity;
9
11
 
10
12
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { getResourceTitle } from './pluginUtils/getResourceTitle.js';\nimport type { SiteActivityLog } from './collections/siteActivity.js';\nimport { formatUserDisplay } from './pluginUtils/formatUserDisplay.js';\nimport { getCollectionLabel } from './pluginUtils/getCollectionLabel.js';\nimport { payloadLoggsPlugin, siteActivity, siteActivityPlugin } from './plugin.js';\nimport { siteActivity as siteActivityCollection } from './collections/siteActivity.js';\nimport { SITE_ACTIVITY_SLUG, SiteActivityCollection } from './collections/SiteActivityCollection.js';\n\nexport type { SiteActivityLogData } from './collections/SiteActivityCollection.js';\nexport type { AutomationConfig, PluginConfig } from './types/config.js';\nexport type { SiteActivityLog };\n\nexport {\n formatUserDisplay,\n getCollectionLabel,\n getResourceTitle,\n payloadLoggsPlugin,\n SITE_ACTIVITY_SLUG,\n siteActivity,\n SiteActivityCollection,\n siteActivityCollection,\n siteActivityPlugin,\n};\n\nexport default siteActivity;\n"],"names":["getResourceTitle","formatUserDisplay","getCollectionLabel","payloadLoggsPlugin","siteActivity","siteActivityPlugin","siteActivityCollection","SITE_ACTIVITY_SLUG","SiteActivityCollection"],"mappings":"AAAA,SAASA,gBAAgB,QAAQ,oCAAoC;AAErE,SAASC,iBAAiB,QAAQ,qCAAqC;AACvE,SAASC,kBAAkB,QAAQ,sCAAsC;AACzE,SAASC,kBAAkB,EAAEC,YAAY,EAAEC,kBAAkB,QAAQ,cAAc;AACnF,SAASD,gBAAgBE,sBAAsB,QAAQ,gCAAgC;AACvF,SAASC,kBAAkB,EAAEC,sBAAsB,QAAQ,0CAA0C;AAMrG,SACEP,iBAAiB,EACjBC,kBAAkB,EAClBF,gBAAgB,EAChBG,kBAAkB,EAClBI,kBAAkB,EAClBH,YAAY,EACZI,sBAAsB,EACtBF,sBAAsB,EACtBD,kBAAkB,GAClB;AAEF,eAAeD,aAAa"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { ActivityEvent } from './types/events.js';\nimport { getResourceTitle } from './pluginUtils/getResourceTitle.js';\nimport type { SiteActivityLog } from './collections/siteActivity.js';\nimport { formatUserDisplay } from './pluginUtils/formatUserDisplay.js';\nimport { getCollectionLabel } from './pluginUtils/getCollectionLabel.js';\nimport { payloadLoggsPlugin, siteActivity, siteActivityPlugin } from './plugin.js';\nimport { siteActivity as siteActivityCollection } from './collections/siteActivity.js';\nimport { SITE_ACTIVITY_SLUG, SiteActivityCollection } from './collections/SiteActivityCollection.js';\nimport { getActivityEvent, getActivityLabel, getCollectionActivityDetails, getGlobalActivityDetails } from './pluginUtils/getActivityDetails.js';\n\nexport type { SiteActivityLogData } from './collections/SiteActivityCollection.js';\nexport type { AutomationConfig, PluginConfig } from './types/config.js';\nexport type { ActivityClassificationParams, ActivityDetails } from './types/events.js';\nexport type { SiteActivityLog };\n\nexport {\n ActivityEvent,\n formatUserDisplay,\n getActivityEvent,\n getActivityLabel,\n getCollectionActivityDetails,\n getCollectionLabel,\n getGlobalActivityDetails,\n getResourceTitle,\n payloadLoggsPlugin,\n SITE_ACTIVITY_SLUG,\n siteActivity,\n SiteActivityCollection,\n siteActivityCollection,\n siteActivityPlugin,\n};\n\nexport default siteActivity;\n"],"names":["ActivityEvent","getResourceTitle","formatUserDisplay","getCollectionLabel","payloadLoggsPlugin","siteActivity","siteActivityPlugin","siteActivityCollection","SITE_ACTIVITY_SLUG","SiteActivityCollection","getActivityEvent","getActivityLabel","getCollectionActivityDetails","getGlobalActivityDetails"],"mappings":"AAAA,SAASA,aAAa,QAAQ,oBAAoB;AAClD,SAASC,gBAAgB,QAAQ,oCAAoC;AAErE,SAASC,iBAAiB,QAAQ,qCAAqC;AACvE,SAASC,kBAAkB,QAAQ,sCAAsC;AACzE,SAASC,kBAAkB,EAAEC,YAAY,EAAEC,kBAAkB,QAAQ,cAAc;AACnF,SAASD,gBAAgBE,sBAAsB,QAAQ,gCAAgC;AACvF,SAASC,kBAAkB,EAAEC,sBAAsB,QAAQ,0CAA0C;AACrG,SAASC,gBAAgB,EAAEC,gBAAgB,EAAEC,4BAA4B,EAAEC,wBAAwB,QAAQ,sCAAsC;AAOjJ,SACEb,aAAa,EACbE,iBAAiB,EACjBQ,gBAAgB,EAChBC,gBAAgB,EAChBC,4BAA4B,EAC5BT,kBAAkB,EAClBU,wBAAwB,EACxBZ,gBAAgB,EAChBG,kBAAkB,EAClBI,kBAAkB,EAClBH,YAAY,EACZI,sBAAsB,EACtBF,sBAAsB,EACtBD,kBAAkB,GAClB;AAEF,eAAeD,aAAa"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ import type { CollectionConfig, GlobalConfig } from 'payload';
2
+ import { ActivityEvent } from '../types/events.js';
3
+ import type { SiteActivityLogData } from '../collections/SiteActivityCollection.js';
4
+ import type { ActivityClassificationParams, ActivityDetails } from '../types/events.js';
5
+ export declare function getActivityLabel(event: ActivityEvent, resourceLabel: string, isGlobal?: boolean): string;
6
+ export declare function eventToOperation(event: ActivityEvent): SiteActivityLogData['operation'];
7
+ export declare function getActivityEvent(params: ActivityClassificationParams): ActivityEvent;
8
+ export declare function getCollectionActivityDetails(collection: CollectionConfig, operation: 'create' | 'update', doc: Record<string, unknown> | undefined, previousDoc?: Record<string, unknown>, req?: any): ActivityDetails;
9
+ export declare function getGlobalActivityDetails(globalConfig: GlobalConfig, doc: Record<string, unknown> | undefined, previousDoc?: Record<string, unknown>, req?: any): ActivityDetails;
@@ -0,0 +1,132 @@
1
+ import { ActivityEvent } from '../types/events.js';
2
+ import { getCollectionLabel } from './getCollectionLabel.js';
3
+ export function getActivityLabel(event, resourceLabel, isGlobal = false) {
4
+ const prefix = isGlobal ? `Global ${resourceLabel}` : resourceLabel;
5
+ switch(event){
6
+ case ActivityEvent.CREATED:
7
+ return `${prefix} Created`;
8
+ case ActivityEvent.UPDATED:
9
+ return `${prefix} Updated`;
10
+ case ActivityEvent.DELETED:
11
+ return `${prefix} Deleted`;
12
+ case ActivityEvent.PUBLISHED:
13
+ return `${prefix} Published`;
14
+ case ActivityEvent.UNPUBLISHED:
15
+ return `${prefix} Unpublished`;
16
+ case ActivityEvent.DRAFT_SAVED:
17
+ return resourceLabel.toLowerCase() === 'page' ? 'Changes Saved as Draft' : `${prefix} Changes Saved as Draft`;
18
+ case ActivityEvent.USER_LOGIN:
19
+ return 'User Logged In';
20
+ case ActivityEvent.USER_LOGOUT:
21
+ return 'User Logged Out';
22
+ case ActivityEvent.USER_LOGIN_FAILED:
23
+ return 'Failed Login';
24
+ case ActivityEvent.USER_SESSION_EXPIRED:
25
+ return 'Session Expired';
26
+ case ActivityEvent.RESTORED:
27
+ return `${prefix} Restored`;
28
+ case ActivityEvent.DUPLICATED:
29
+ return `${prefix} Duplicated`;
30
+ default:
31
+ return `${prefix} Updated`;
32
+ }
33
+ }
34
+ export function eventToOperation(event) {
35
+ switch(event){
36
+ case ActivityEvent.CREATED:
37
+ return 'create';
38
+ case ActivityEvent.UPDATED:
39
+ return 'update';
40
+ case ActivityEvent.DELETED:
41
+ return 'delete';
42
+ case ActivityEvent.PUBLISHED:
43
+ return 'publish';
44
+ case ActivityEvent.UNPUBLISHED:
45
+ return 'unpublish';
46
+ case ActivityEvent.DRAFT_SAVED:
47
+ return 'draft_saved';
48
+ case ActivityEvent.USER_LOGIN:
49
+ return 'login';
50
+ case ActivityEvent.USER_LOGOUT:
51
+ return 'logout';
52
+ default:
53
+ return 'update';
54
+ }
55
+ }
56
+ export function getActivityEvent(params) {
57
+ const { operation, previousDoc, doc, req, context } = params;
58
+ if (operation === 'login') {
59
+ return ActivityEvent.USER_LOGIN;
60
+ }
61
+ if (operation === 'logout') {
62
+ return ActivityEvent.USER_LOGOUT;
63
+ }
64
+ if (operation === 'delete') {
65
+ return ActivityEvent.DELETED;
66
+ }
67
+ // Explicit activity event override passed in request or context
68
+ const reqContext = req?.context || context;
69
+ if (reqContext?.activityEvent && typeof reqContext.activityEvent === 'string') {
70
+ const explicitEvent = reqContext.activityEvent;
71
+ if (Object.values(ActivityEvent).includes(explicitEvent)) {
72
+ return explicitEvent;
73
+ }
74
+ }
75
+ const currentStatus = doc && typeof doc === 'object' && '_status' in doc && typeof doc._status === 'string' ? doc._status : undefined;
76
+ const prevStatus = previousDoc && typeof previousDoc === 'object' && '_status' in previousDoc && typeof previousDoc._status === 'string' ? previousDoc._status : undefined;
77
+ const isCreate = operation === 'create' || !previousDoc && operation !== 'update';
78
+ if (currentStatus) {
79
+ if (isCreate) {
80
+ // Creation of a document with draft or published status
81
+ return ActivityEvent.CREATED;
82
+ }
83
+ // Check transition states for existing document update
84
+ if (prevStatus === 'draft' && currentStatus === 'published') {
85
+ return ActivityEvent.PUBLISHED;
86
+ }
87
+ if (prevStatus === 'published' && currentStatus === 'draft') {
88
+ // Distinguish explicit unpublish vs saving draft of published page
89
+ const isExplicitUnpublish = Boolean(reqContext?.unpublish || reqContext?._payloadUnpublish || reqContext?.isUnpublishing || req?.url?.includes('/unpublish') || req?.route?.path?.includes('/unpublish'));
90
+ return isExplicitUnpublish ? ActivityEvent.UNPUBLISHED : ActivityEvent.DRAFT_SAVED;
91
+ }
92
+ if (currentStatus === 'draft') {
93
+ return ActivityEvent.DRAFT_SAVED;
94
+ }
95
+ if (currentStatus === 'published') {
96
+ return ActivityEvent.UPDATED;
97
+ }
98
+ }
99
+ return isCreate ? ActivityEvent.CREATED : ActivityEvent.UPDATED;
100
+ }
101
+ export function getCollectionActivityDetails(collection, operation, doc, previousDoc, req) {
102
+ const label = getCollectionLabel(collection);
103
+ const event = getActivityEvent({
104
+ operation,
105
+ doc,
106
+ previousDoc,
107
+ req,
108
+ collectionSlug: collection.slug
109
+ });
110
+ return {
111
+ event,
112
+ title: getActivityLabel(event, label, false),
113
+ operation: eventToOperation(event)
114
+ };
115
+ }
116
+ export function getGlobalActivityDetails(globalConfig, doc, previousDoc, req) {
117
+ const label = getCollectionLabel(globalConfig);
118
+ const event = getActivityEvent({
119
+ operation: 'update',
120
+ doc,
121
+ previousDoc,
122
+ req,
123
+ collectionSlug: globalConfig.slug
124
+ });
125
+ return {
126
+ event,
127
+ title: getActivityLabel(event, label, true),
128
+ operation: eventToOperation(event)
129
+ };
130
+ }
131
+
132
+ //# sourceMappingURL=getActivityDetails.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/pluginUtils/getActivityDetails.ts"],"sourcesContent":["import type { CollectionConfig, GlobalConfig } from 'payload';\n\nimport { ActivityEvent } from '../types/events.js';\nimport { getCollectionLabel } from './getCollectionLabel.js';\nimport type { SiteActivityLogData } from '../collections/SiteActivityCollection.js';\nimport type { ActivityClassificationParams, ActivityDetails } from '../types/events.js';\n\nexport function getActivityLabel(\n event: ActivityEvent,\n resourceLabel: string,\n isGlobal = false,\n): string {\n const prefix = isGlobal ? `Global ${resourceLabel}` : resourceLabel;\n\n switch (event) {\n case ActivityEvent.CREATED:\n return `${prefix} Created`;\n case ActivityEvent.UPDATED:\n return `${prefix} Updated`;\n case ActivityEvent.DELETED:\n return `${prefix} Deleted`;\n case ActivityEvent.PUBLISHED:\n return `${prefix} Published`;\n case ActivityEvent.UNPUBLISHED:\n return `${prefix} Unpublished`;\n case ActivityEvent.DRAFT_SAVED:\n return resourceLabel.toLowerCase() === 'page'\n ? 'Changes Saved as Draft'\n : `${prefix} Changes Saved as Draft`;\n case ActivityEvent.USER_LOGIN:\n return 'User Logged In';\n case ActivityEvent.USER_LOGOUT:\n return 'User Logged Out';\n case ActivityEvent.USER_LOGIN_FAILED:\n return 'Failed Login';\n case ActivityEvent.USER_SESSION_EXPIRED:\n return 'Session Expired';\n case ActivityEvent.RESTORED:\n return `${prefix} Restored`;\n case ActivityEvent.DUPLICATED:\n return `${prefix} Duplicated`;\n default:\n return `${prefix} Updated`;\n }\n}\n\nexport function eventToOperation(event: ActivityEvent): SiteActivityLogData['operation'] {\n switch (event) {\n case ActivityEvent.CREATED:\n return 'create';\n case ActivityEvent.UPDATED:\n return 'update';\n case ActivityEvent.DELETED:\n return 'delete';\n case ActivityEvent.PUBLISHED:\n return 'publish';\n case ActivityEvent.UNPUBLISHED:\n return 'unpublish';\n case ActivityEvent.DRAFT_SAVED:\n return 'draft_saved';\n case ActivityEvent.USER_LOGIN:\n return 'login';\n case ActivityEvent.USER_LOGOUT:\n return 'logout';\n default:\n return 'update';\n }\n}\n\nexport function getActivityEvent(params: ActivityClassificationParams): ActivityEvent {\n const { operation, previousDoc, doc, req, context } = params;\n\n if (operation === 'login') {\n return ActivityEvent.USER_LOGIN;\n }\n if (operation === 'logout') {\n return ActivityEvent.USER_LOGOUT;\n }\n if (operation === 'delete') {\n return ActivityEvent.DELETED;\n }\n\n // Explicit activity event override passed in request or context\n const reqContext = req?.context || context;\n if (reqContext?.activityEvent && typeof reqContext.activityEvent === 'string') {\n const explicitEvent = reqContext.activityEvent as ActivityEvent;\n if (Object.values(ActivityEvent).includes(explicitEvent)) {\n return explicitEvent;\n }\n }\n\n const currentStatus = doc && typeof doc === 'object' && '_status' in doc && typeof doc._status === 'string'\n ? doc._status\n : undefined;\n const prevStatus = previousDoc && typeof previousDoc === 'object' && '_status' in previousDoc && typeof previousDoc._status === 'string'\n ? previousDoc._status\n : undefined;\n\n const isCreate = operation === 'create' || (!previousDoc && operation !== 'update');\n\n if (currentStatus) {\n if (isCreate) {\n // Creation of a document with draft or published status\n return ActivityEvent.CREATED;\n }\n\n // Check transition states for existing document update\n if (prevStatus === 'draft' && currentStatus === 'published') {\n return ActivityEvent.PUBLISHED;\n }\n\n if (prevStatus === 'published' && currentStatus === 'draft') {\n // Distinguish explicit unpublish vs saving draft of published page\n const isExplicitUnpublish = Boolean(\n reqContext?.unpublish\n || reqContext?._payloadUnpublish\n || reqContext?.isUnpublishing\n || req?.url?.includes('/unpublish')\n || req?.route?.path?.includes('/unpublish'),\n );\n\n return isExplicitUnpublish ? ActivityEvent.UNPUBLISHED : ActivityEvent.DRAFT_SAVED;\n }\n\n if (currentStatus === 'draft') {\n return ActivityEvent.DRAFT_SAVED;\n }\n\n if (currentStatus === 'published') {\n return ActivityEvent.UPDATED;\n }\n }\n\n return isCreate ? ActivityEvent.CREATED : ActivityEvent.UPDATED;\n}\n\nexport function getCollectionActivityDetails(\n collection: CollectionConfig,\n operation: 'create' | 'update',\n doc: Record<string, unknown> | undefined,\n previousDoc?: Record<string, unknown>,\n req?: any,\n): ActivityDetails {\n const label = getCollectionLabel(collection);\n const event = getActivityEvent({\n operation,\n doc,\n previousDoc,\n req,\n collectionSlug: collection.slug,\n });\n\n return {\n event,\n title: getActivityLabel(event, label, false),\n operation: eventToOperation(event),\n };\n}\n\nexport function getGlobalActivityDetails(\n globalConfig: GlobalConfig,\n doc: Record<string, unknown> | undefined,\n previousDoc?: Record<string, unknown>,\n req?: any,\n): ActivityDetails {\n const label = getCollectionLabel(globalConfig);\n const event = getActivityEvent({\n operation: 'update',\n doc,\n previousDoc,\n req,\n collectionSlug: globalConfig.slug,\n });\n\n return {\n event,\n title: getActivityLabel(event, label, true),\n operation: eventToOperation(event),\n };\n}\n"],"names":["ActivityEvent","getCollectionLabel","getActivityLabel","event","resourceLabel","isGlobal","prefix","CREATED","UPDATED","DELETED","PUBLISHED","UNPUBLISHED","DRAFT_SAVED","toLowerCase","USER_LOGIN","USER_LOGOUT","USER_LOGIN_FAILED","USER_SESSION_EXPIRED","RESTORED","DUPLICATED","eventToOperation","getActivityEvent","params","operation","previousDoc","doc","req","context","reqContext","activityEvent","explicitEvent","Object","values","includes","currentStatus","_status","undefined","prevStatus","isCreate","isExplicitUnpublish","Boolean","unpublish","_payloadUnpublish","isUnpublishing","url","route","path","getCollectionActivityDetails","collection","label","collectionSlug","slug","title","getGlobalActivityDetails","globalConfig"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -7,7 +7,7 @@ export type CollectionHookDebugConfig = {
7
7
  skipDatabaseSave?: true;
8
8
  } | true;
9
9
  export type CollectionHooksKeys = keyof NonNullable<CollectionConfig['hooks']>;
10
- export type CollectionHooksOperation = AllOperations | 'read' | 'delete' | 'error' | 'login' | 'logout' | 'me' | 'refresh' | 'forgotPassword' | '';
10
+ export type CollectionHooksOperation = AllOperations | 'read' | 'delete' | 'error' | 'login' | 'logout' | 'me' | 'refresh' | 'forgotPassword' | 'publish' | 'unpublish' | '';
11
11
  export type CollectionHooksArgsParameterUnion = Parameters<NonNullable<NonNullable<CollectionConfig['hooks']>[CollectionHooksKeys]>[number]>[0];
12
12
  export type PayloadCollectionHooksMap = {
13
13
  [K in CollectionHooksKeys]: NonNullable<NonNullable<CollectionConfig['hooks']>[K]>[number];
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/types/collection.ts"],"sourcesContent":["import type { AllOperations, CollectionConfig, PayloadTypes } from 'payload';\n\nimport type { SiteActivityLog } from '../collections/siteActivity.js';\n\nexport type OperationDebugConfig = {\n skipDatabaseSave?: boolean;\n} | true;\n\nexport type CollectionHookDebugConfig = {\n skipDatabaseSave?: true;\n} | true;\n\nexport type CollectionHooksKeys = keyof NonNullable<CollectionConfig['hooks']>;\nexport type CollectionHooksOperation = AllOperations | 'read' | 'delete' | 'error' | 'login' | 'logout' | 'me' | 'refresh' | 'forgotPassword' | '';\nexport type CollectionHooksArgsParameterUnion = Parameters<\n NonNullable<\n NonNullable<\n CollectionConfig['hooks']\n >[CollectionHooksKeys]\n >[number]\n>[0];\n\nexport type PayloadCollectionHooksMap = {\n [K in CollectionHooksKeys]: NonNullable<NonNullable<CollectionConfig['hooks']>[K]>[number]\n};\nexport type CollectionsHookConfigForTracking = {\n [K in keyof NonNullable<CollectionConfig['hooks']>]:\n Partial<\n {\n // @ts-expect-error\n [O in Parameters<\n NonNullable<\n NonNullable<\n CollectionConfig['hooks']\n >[K]\n >[number]\n >[0]['operation']]: CollectionOperationLogConfig | boolean\n } & CollectionHookLevelLogConfig<K>\n > | boolean\n};\n\nexport interface CollectionOperationLogConfig<\n HookName extends CollectionHooksKeys = CollectionHooksKeys,\n> {\n customLogger?: (\n args: Parameters<PayloadCollectionHooksMap[HookName]>[0],\n fields: Omit<SiteActivityLog, 'hook' | 'operation'>,\n ) => any | Promise<any>;\n enabled?: boolean;\n debug?: OperationDebugConfig;\n}\n\nexport interface CollectionHookLevelLogConfig<\n HookName extends CollectionHooksKeys = CollectionHooksKeys,\n> {\n customLogger?: (\n args: Parameters<PayloadCollectionHooksMap[HookName]>[0],\n fields: Omit<SiteActivityLog, 'hook'>,\n ) => Omit<SiteActivityLog, 'hook'> | Promise<Omit<SiteActivityLog, 'hook'>>;\n enabled?: boolean;\n debug?: CollectionHookDebugConfig;\n}\n\nexport interface TrackedCollection {\n hooks?: Partial<CollectionsHookConfigForTracking>;\n slug: keyof PayloadTypes['collections'];\n}\nexport interface CollectionsTrackConfig {\n track: TrackedCollection[];\n}\n"],"names":[],"mappings":"AAmEA,WAEC"}
1
+ {"version":3,"sources":["../../src/types/collection.ts"],"sourcesContent":["import type { AllOperations, CollectionConfig, PayloadTypes } from 'payload';\n\nimport type { SiteActivityLog } from '../collections/siteActivity.js';\n\nexport type OperationDebugConfig = {\n skipDatabaseSave?: boolean;\n} | true;\n\nexport type CollectionHookDebugConfig = {\n skipDatabaseSave?: true;\n} | true;\n\nexport type CollectionHooksKeys = keyof NonNullable<CollectionConfig['hooks']>;\nexport type CollectionHooksOperation = AllOperations | 'read' | 'delete' | 'error' | 'login' | 'logout' | 'me' | 'refresh' | 'forgotPassword' | 'publish' | 'unpublish' | '';\nexport type CollectionHooksArgsParameterUnion = Parameters<\n NonNullable<\n NonNullable<\n CollectionConfig['hooks']\n >[CollectionHooksKeys]\n >[number]\n>[0];\n\nexport type PayloadCollectionHooksMap = {\n [K in CollectionHooksKeys]: NonNullable<NonNullable<CollectionConfig['hooks']>[K]>[number]\n};\nexport type CollectionsHookConfigForTracking = {\n [K in keyof NonNullable<CollectionConfig['hooks']>]:\n Partial<\n {\n // @ts-expect-error\n [O in Parameters<\n NonNullable<\n NonNullable<\n CollectionConfig['hooks']\n >[K]\n >[number]\n >[0]['operation']]: CollectionOperationLogConfig | boolean\n } & CollectionHookLevelLogConfig<K>\n > | boolean\n};\n\nexport interface CollectionOperationLogConfig<\n HookName extends CollectionHooksKeys = CollectionHooksKeys,\n> {\n customLogger?: (\n args: Parameters<PayloadCollectionHooksMap[HookName]>[0],\n fields: Omit<SiteActivityLog, 'hook' | 'operation'>,\n ) => any | Promise<any>;\n enabled?: boolean;\n debug?: OperationDebugConfig;\n}\n\nexport interface CollectionHookLevelLogConfig<\n HookName extends CollectionHooksKeys = CollectionHooksKeys,\n> {\n customLogger?: (\n args: Parameters<PayloadCollectionHooksMap[HookName]>[0],\n fields: Omit<SiteActivityLog, 'hook'>,\n ) => Omit<SiteActivityLog, 'hook'> | Promise<Omit<SiteActivityLog, 'hook'>>;\n enabled?: boolean;\n debug?: CollectionHookDebugConfig;\n}\n\nexport interface TrackedCollection {\n hooks?: Partial<CollectionsHookConfigForTracking>;\n slug: keyof PayloadTypes['collections'];\n}\nexport interface CollectionsTrackConfig {\n track: TrackedCollection[];\n}\n"],"names":[],"mappings":"AAmEA,WAEC"}
@@ -0,0 +1,27 @@
1
+ export declare enum ActivityEvent {
2
+ USER_LOGIN = "USER_LOGIN",
3
+ USER_LOGOUT = "USER_LOGOUT",
4
+ USER_LOGIN_FAILED = "USER_LOGIN_FAILED",
5
+ USER_SESSION_EXPIRED = "USER_SESSION_EXPIRED",
6
+ CREATED = "CREATED",
7
+ UPDATED = "UPDATED",
8
+ DELETED = "DELETED",
9
+ DRAFT_SAVED = "DRAFT_SAVED",
10
+ PUBLISHED = "PUBLISHED",
11
+ UNPUBLISHED = "UNPUBLISHED",
12
+ RESTORED = "RESTORED",
13
+ DUPLICATED = "DUPLICATED"
14
+ }
15
+ export interface ActivityClassificationParams {
16
+ operation: 'create' | 'update' | 'delete' | 'login' | 'logout';
17
+ collectionSlug?: string;
18
+ previousDoc?: Record<string, unknown>;
19
+ doc?: Record<string, unknown>;
20
+ req?: any;
21
+ context?: Record<string, unknown>;
22
+ }
23
+ export interface ActivityDetails {
24
+ event: ActivityEvent;
25
+ title: string;
26
+ operation: 'create' | 'update' | 'delete' | 'login' | 'logout' | 'publish' | 'unpublish' | 'draft_saved';
27
+ }
@@ -0,0 +1,17 @@
1
+ export var ActivityEvent = /*#__PURE__*/ function(ActivityEvent) {
2
+ ActivityEvent["USER_LOGIN"] = "USER_LOGIN";
3
+ ActivityEvent["USER_LOGOUT"] = "USER_LOGOUT";
4
+ ActivityEvent["USER_LOGIN_FAILED"] = "USER_LOGIN_FAILED";
5
+ ActivityEvent["USER_SESSION_EXPIRED"] = "USER_SESSION_EXPIRED";
6
+ ActivityEvent["CREATED"] = "CREATED";
7
+ ActivityEvent["UPDATED"] = "UPDATED";
8
+ ActivityEvent["DELETED"] = "DELETED";
9
+ ActivityEvent["DRAFT_SAVED"] = "DRAFT_SAVED";
10
+ ActivityEvent["PUBLISHED"] = "PUBLISHED";
11
+ ActivityEvent["UNPUBLISHED"] = "UNPUBLISHED";
12
+ ActivityEvent["RESTORED"] = "RESTORED";
13
+ ActivityEvent["DUPLICATED"] = "DUPLICATED";
14
+ return ActivityEvent;
15
+ }({});
16
+
17
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/types/events.ts"],"sourcesContent":["export enum ActivityEvent {\n USER_LOGIN = 'USER_LOGIN',\n USER_LOGOUT = 'USER_LOGOUT',\n USER_LOGIN_FAILED = 'USER_LOGIN_FAILED',\n USER_SESSION_EXPIRED = 'USER_SESSION_EXPIRED',\n\n CREATED = 'CREATED',\n UPDATED = 'UPDATED',\n DELETED = 'DELETED',\n\n DRAFT_SAVED = 'DRAFT_SAVED',\n PUBLISHED = 'PUBLISHED',\n UNPUBLISHED = 'UNPUBLISHED',\n\n RESTORED = 'RESTORED',\n DUPLICATED = 'DUPLICATED',\n}\n\nexport interface ActivityClassificationParams {\n operation: 'create' | 'update' | 'delete' | 'login' | 'logout';\n collectionSlug?: string;\n previousDoc?: Record<string, unknown>;\n doc?: Record<string, unknown>;\n req?: any;\n context?: Record<string, unknown>;\n}\n\nexport interface ActivityDetails {\n event: ActivityEvent;\n title: string;\n operation: 'create' | 'update' | 'delete' | 'login' | 'logout' | 'publish' | 'unpublish' | 'draft_saved';\n}\n"],"names":["ActivityEvent"],"mappings":"AAAA,OAAO,IAAA,AAAKA,uCAAAA;;;;;;;;;;;;;WAAAA;MAgBX"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@brandlift/payload-loggs",
3
3
  "type": "module",
4
- "version": "1.1.0",
4
+ "version": "1.3.0",
5
5
  "packageManager": "pnpm@10.2.0",
6
6
  "description": "Zero-config activity feed, audit logging, and security tracking plugin for Payload CMS",
7
7
  "author": {