strapi-plugin-bulk-updater 1.4.10 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/_chunks/{BulkUpdater-CHdA0546.mjs → BulkUpdater-BiSkkAHF.mjs} +673 -147
- package/dist/_chunks/BulkUpdater-BiSkkAHF.mjs.map +1 -0
- package/dist/_chunks/{BulkUpdater-C0uPoso2.js → BulkUpdater-JZW74XM4.js} +672 -146
- package/dist/_chunks/BulkUpdater-JZW74XM4.js.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +687 -231
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +687 -231
- package/dist/server/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/_chunks/BulkUpdater-C0uPoso2.js.map +0 -1
- package/dist/_chunks/BulkUpdater-CHdA0546.mjs.map +0 -1
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../server/src/routes/index.ts","../../server/src/content-types/audit-log.ts","../../server/src/content-types/index.ts","../../server/src/controllers/bulk-updater.ts","../../server/src/controllers/audit.ts","../../server/src/controllers/validation-rules.ts","../../server/src/controllers/csv.ts","../../server/src/services/content-history.ts","../../server/src/services/bulk-updater.ts","../../server/src/services/audit.ts","../../server/src/services/validation-rules.ts","../../server/src/services/csv.ts","../../server/src/index.ts"],"sourcesContent":["export default {\n admin: {\n type: 'admin',\n routes: [\n {\n method: 'GET',\n path: '/models',\n handler: 'bulkUpdater.getModels',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/collections/:uid/entries',\n handler: 'bulkUpdater.getCollectionEntries',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/relation-options',\n handler: 'bulkUpdater.getRelationOptions',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/batch-update',\n handler: 'bulkUpdater.batchUpdate',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/batch-publish',\n handler: 'bulkUpdater.batchPublish',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/preview',\n handler: 'bulkUpdater.previewBatch',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/pending-batches',\n handler: 'bulkUpdater.getPendingBatches',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/batches/:batchId/approve',\n handler: 'bulkUpdater.approveBatch',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/batches/:batchId/reject',\n handler: 'bulkUpdater.rejectBatch',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/batches/:batchId/execute-now',\n handler: 'bulkUpdater.executeNow',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/batches/recent',\n handler: 'bulkUpdater.getRecentBatches',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/batches/:batchId/status',\n handler: 'bulkUpdater.getBatchStatus',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/batches/:batchId/report',\n handler: 'bulkUpdater.getBatchReport',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/audit/history',\n handler: 'audit.getHistory',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/audit/:batchId/rollback',\n handler: 'audit.rollback',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/validation-rules',\n handler: 'validationRules.getRules',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/validation-rules',\n handler: 'validationRules.saveRule',\n config: {\n policies: [],\n },\n },\n {\n method: 'DELETE',\n path: '/validation-rules/:id',\n handler: 'validationRules.deleteRule',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/validation-rules/:id/toggle',\n handler: 'validationRules.toggleRule',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/validation-rules/:id/scan',\n handler: 'validationRules.scanViolations',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/csv/template/:uid',\n handler: 'csv.getTemplate',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/csv/export/:uid',\n handler: 'csv.exportCollection',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/csv/export/:uid',\n handler: 'csv.exportCollection',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/csv/export-bulk',\n handler: 'csv.exportBulk',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/csv/export-violations/:ruleId',\n handler: 'csv.exportViolations',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/csv/import',\n handler: 'csv.importCsv',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/csv/import-chunk',\n handler: 'csv.importChunk',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/csv/validate-preflight',\n handler: 'csv.validatePreflight',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/csv/submit-batch',\n handler: 'csv.submitBatch',\n config: {\n policies: [],\n },\n },\n ],\n },\n};\n","export default {\n collectionName: 'bulk_updater_audit_logs',\n info: {\n singularName: 'audit-log',\n pluralName: 'audit-logs',\n displayName: 'Bulk Updater Audit Log',\n description: 'Internal audit trail for bulk attribute and relation updates',\n },\n options: {\n draftAndPublish: false,\n },\n pluginOptions: {\n 'content-manager': {\n visible: true,\n },\n 'content-type-builder': {\n visible: false,\n },\n },\n attributes: {\n batchId: {\n type: 'string',\n required: true,\n },\n attribute: {\n type: 'string',\n required: true,\n },\n value: {\n type: 'text',\n },\n userEmail: {\n type: 'string',\n },\n userName: {\n type: 'string',\n },\n updatedCount: {\n type: 'integer',\n default: 0,\n },\n skippedCount: {\n type: 'integer',\n default: 0,\n },\n totalTargets: {\n type: 'integer',\n default: 0,\n },\n diffs: {\n type: 'json',\n },\n isRolledBack: {\n type: 'boolean',\n default: false,\n },\n rolledBackAt: {\n type: 'datetime',\n },\n rolledBackBy: {\n type: 'string',\n },\n executedAt: {\n type: 'datetime',\n },\n },\n};\n","import auditLog from './audit-log';\n\nexport default {\n 'audit-log': {\n schema: auditLog,\n },\n};\n","import type { Core } from '@strapi/strapi';\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => ({\n async getModels(ctx: any) {\n try {\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const data = await service.getModels();\n\n if (data?.etag) {\n ctx.set('ETag', data.etag);\n ctx.set('Cache-Control', 'private, no-cache');\n }\n\n ctx.body = data;\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async getCollectionEntries(ctx: any) {\n try {\n const { uid } = ctx.params;\n const { page, pageSize, attribute, searchAttribute, filterOperator, filterQuery, search, sortField, sortOrder } = ctx.query;\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const data = await service.getCollectionEntries(uid, {\n page: page ? Number(page) : 1,\n pageSize: pageSize ? Number(pageSize) : 10,\n attribute: attribute ? String(attribute) : undefined,\n searchAttribute: searchAttribute ? String(searchAttribute) : undefined,\n filterOperator: filterOperator ? String(filterOperator) : undefined,\n filterQuery: filterQuery !== undefined ? String(filterQuery) : undefined,\n search: search ? String(search) : undefined,\n sortField: sortField ? String(sortField) : undefined,\n sortOrder: sortOrder === 'asc' ? 'asc' : 'desc',\n });\n\n if (data?.etag) {\n ctx.set('ETag', data.etag);\n ctx.set('Cache-Control', 'private, no-cache');\n }\n\n ctx.body = { success: true, ...data };\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async getRelationOptions(ctx: any) {\n try {\n const { targetUid } = ctx.query;\n if (!targetUid) {\n ctx.status = 400;\n ctx.body = { success: false, error: 'targetUid is required' };\n return;\n }\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const data = await service.getRelationOptions(String(targetUid));\n ctx.body = { success: true, ...data };\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async batchUpdate(ctx: any) {\n try {\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const currentUser = ctx.state.user;\n const result = await service.batchUpdate(ctx.request.body || {}, currentUser);\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 400;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async batchPublish(ctx: any) {\n try {\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const currentUser = ctx.state.user;\n const result = await service.batchPublish(ctx.request.body || {}, currentUser);\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 400;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async previewBatch(ctx: any) {\n try {\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const result = await service.previewBatch(ctx.request.body || {});\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 400;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async getPendingBatches(ctx: any) {\n try {\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const result = await service.getPendingBatches();\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async approveBatch(ctx: any) {\n try {\n const { batchId } = ctx.params;\n const { executeImmediately = true } = ctx.request.body || {};\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const currentUser = ctx.state.user;\n const result = await service.approveBatch(batchId, currentUser, { executeImmediately });\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 400;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async rejectBatch(ctx: any) {\n try {\n const { batchId } = ctx.params;\n const { reason } = ctx.request.body || {};\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const currentUser = ctx.state.user;\n const result = await service.rejectBatch(batchId, currentUser, reason);\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 400;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async executeNow(ctx: any) {\n try {\n const { batchId } = ctx.params;\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const currentUser = ctx.state.user;\n const result = await service.executeNow(batchId, currentUser);\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 400;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async getBatchStatus(ctx: any) {\n try {\n const { batchId } = ctx.params;\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const result = await service.getBatchStatus(batchId);\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 404;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async getBatchReport(ctx: any) {\n try {\n const { batchId } = ctx.params;\n const { format = 'csv' } = ctx.query;\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const result = await service.getBatchReport(batchId, format);\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async getRecentBatches(ctx: any) {\n try {\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const result = await service.getRecentBatches();\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n});\n","import type { Core } from '@strapi/strapi';\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => ({\n async getHistory(ctx: any) {\n try {\n const service = strapi.plugin('bulk-updater').service('audit');\n const data = await service.getHistory();\n ctx.body = data;\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async rollback(ctx: any) {\n try {\n const { batchId } = ctx.params;\n const service = strapi.plugin('bulk-updater').service('audit');\n const currentUser = ctx.state.user;\n const result = await service.rollbackBatch(batchId, currentUser);\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 400;\n ctx.body = { success: false, error: err.message };\n }\n },\n});\n","import type { Core } from '@strapi/strapi';\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => ({\n async getRules(ctx: any) {\n try {\n const rules = await strapi.plugin('bulk-updater').service('validationRules').getRules();\n ctx.body = {\n success: true,\n rules,\n };\n } catch (err: any) {\n ctx.throw(500, err.message);\n }\n },\n\n async saveRule(ctx: any) {\n try {\n const { rule } = ctx.request.body || {};\n if (!rule) {\n return ctx.badRequest('Rule payload is required');\n }\n const saved = await strapi.plugin('bulk-updater').service('validationRules').saveRule(rule);\n ctx.body = {\n success: true,\n rule: saved,\n };\n } catch (err: any) {\n ctx.throw(500, err.message);\n }\n },\n\n async deleteRule(ctx: any) {\n try {\n const { id } = ctx.params;\n if (!id) {\n return ctx.badRequest('Rule ID is required');\n }\n await strapi.plugin('bulk-updater').service('validationRules').deleteRule(id);\n ctx.body = {\n success: true,\n id,\n };\n } catch (err: any) {\n ctx.throw(500, err.message);\n }\n },\n\n async toggleRule(ctx: any) {\n try {\n const { id } = ctx.params;\n const { enabled } = ctx.request.body || {};\n const updated = await strapi.plugin('bulk-updater').service('validationRules').toggleRule(id, enabled);\n if (!updated) {\n return ctx.notFound('Rule not found');\n }\n ctx.body = {\n success: true,\n rule: updated,\n };\n } catch (err: any) {\n ctx.throw(500, err.message);\n }\n },\n\n async scanViolations(ctx: any) {\n try {\n const { id } = ctx.params;\n if (!id) {\n return ctx.badRequest('Rule ID is required');\n }\n const report = await strapi.plugin('bulk-updater').service('validationRules').scanViolations(id);\n ctx.body = {\n success: true,\n ...report,\n };\n } catch (err: any) {\n ctx.throw(500, err.message);\n }\n },\n});\n","import type { Core } from '@strapi/strapi';\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => ({\n async getTemplate(ctx: any) {\n try {\n const { uid } = ctx.params;\n const csvService = strapi.plugin('bulk-updater').service('csv');\n const result = await csvService.getTemplateCsv(uid);\n ctx.body = {\n success: true,\n filename: result.filename,\n csvContent: result.csvContent,\n headers: result.headers,\n };\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async exportCollection(ctx: any) {\n try {\n const { uid } = ctx.params;\n const { search, attribute, filterOperator, filterQuery, limit, documentIds } = {\n ...ctx.query,\n ...(ctx.request?.body || {}),\n };\n const csvService = strapi.plugin('bulk-updater').service('csv');\n\n let parsedDocIds: string[] | undefined;\n if (documentIds) {\n parsedDocIds = Array.isArray(documentIds)\n ? documentIds\n : String(documentIds)\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n }\n\n const result = await csvService.exportCollectionCsv(uid, {\n search: search ? String(search) : undefined,\n attribute: attribute ? String(attribute) : undefined,\n filterOperator: filterOperator ? String(filterOperator) : undefined,\n filterQuery: filterQuery !== undefined ? String(filterQuery) : undefined,\n limit: limit ? Number(limit) : undefined,\n documentIds: parsedDocIds,\n });\n\n ctx.body = {\n success: true,\n filename: result.filename,\n csvContent: result.csvContent,\n count: result.count,\n fields: result.fields,\n };\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async exportBulk(ctx: any) {\n try {\n const { selectedEntries } = ctx.request.body || {};\n const csvService = strapi.plugin('bulk-updater').service('csv');\n const result = await csvService.exportBulkCsv(selectedEntries);\n\n ctx.body = {\n success: true,\n filename: result.filename,\n csvContent: result.csvContent,\n count: result.count,\n isMultiCollection: result.isMultiCollection,\n };\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async exportViolations(ctx: any) {\n try {\n const { ruleId } = ctx.params;\n const csvService = strapi.plugin('bulk-updater').service('csv');\n const result = await csvService.exportViolationsCsv(ruleId);\n\n ctx.body = {\n success: true,\n filename: result.filename,\n csvContent: result.csvContent,\n count: result.count,\n ruleName: result.ruleName,\n };\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async importCsv(ctx: any) {\n try {\n const { uid, csvText, mode, publish, publishStrategy, unreviewedConsent } = ctx.request.body;\n if (!uid) {\n ctx.status = 400;\n ctx.body = { success: false, error: 'Target collection UID is required.' };\n return;\n }\n if (!csvText || typeof csvText !== 'string') {\n ctx.status = 400;\n ctx.body = { success: false, error: 'CSV content is required.' };\n return;\n }\n\n const csvService = strapi.plugin('bulk-updater').service('csv');\n const result = await csvService.importCsv(uid, csvText, {\n mode: mode === 'update' ? 'update' : mode === 'create_or_override' ? 'create_or_override' : 'auto',\n publish: publish !== false,\n publishStrategy: publishStrategy === 'all' ? 'all' : 'safe',\n unreviewedConsent: Boolean(unreviewedConsent),\n user: ctx.state.user,\n });\n\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async importChunk(ctx: any) {\n try {\n const { uid, rows, batchId, isFirstChunk, isLastChunk, startRowNumber, mode, publish, publishStrategy, unreviewedConsent } = ctx.request.body;\n if (!uid) {\n ctx.status = 400;\n ctx.body = { success: false, error: 'Target collection UID is required.' };\n return;\n }\n if (!Array.isArray(rows)) {\n ctx.status = 400;\n ctx.body = { success: false, error: 'Rows array is required.' };\n return;\n }\n\n const csvService = strapi.plugin('bulk-updater').service('csv');\n const result = await csvService.importChunk(uid, rows, {\n batchId: batchId ? String(batchId) : undefined,\n isFirstChunk: Boolean(isFirstChunk),\n isLastChunk: Boolean(isLastChunk),\n startRowNumber: typeof startRowNumber === 'number' ? startRowNumber : undefined,\n mode: mode === 'update' ? 'update' : mode === 'create_or_override' ? 'create_or_override' : 'auto',\n publish: publish !== false,\n publishStrategy: publishStrategy === 'all' ? 'all' : 'safe',\n unreviewedConsent: Boolean(unreviewedConsent),\n user: ctx.state.user,\n });\n\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async validatePreflight(ctx: any) {\n try {\n const { uid, rows, mode } = ctx.request.body;\n if (!uid) {\n ctx.status = 400;\n ctx.body = { success: false, error: 'Target collection UID is required.' };\n return;\n }\n if (!Array.isArray(rows)) {\n ctx.status = 400;\n ctx.body = { success: false, error: 'Rows array is required.' };\n return;\n }\n\n const csvService = strapi.plugin('bulk-updater').service('csv');\n const result = await csvService.validatePreflight(uid, rows, {\n mode: mode === 'update' ? 'update' : mode === 'create_or_override' ? 'create_or_override' : 'auto',\n });\n\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async submitBatch(ctx: any) {\n try {\n const { uid, rows, executionMode, makerNotes, forceImmediate, mode, publish, publishStrategy, unreviewedConsent, unreviewedCount } = ctx.request.body;\n if (!uid) {\n ctx.status = 400;\n ctx.body = { success: false, error: 'Target collection UID is required.' };\n return;\n }\n if (!Array.isArray(rows)) {\n ctx.status = 400;\n ctx.body = { success: false, error: 'Rows array is required.' };\n return;\n }\n\n const csvService = strapi.plugin('bulk-updater').service('csv');\n const result = await csvService.submitBatch(uid, rows, {\n executionMode,\n makerNotes,\n forceImmediate: Boolean(forceImmediate),\n mode: mode === 'update' ? 'update' : mode === 'create_or_override' ? 'create_or_override' : 'auto',\n publish: publish !== false,\n publishStrategy: publishStrategy === 'all' ? 'all' : 'safe',\n unreviewedConsent: Boolean(unreviewedConsent),\n unreviewedCount: typeof unreviewedCount === 'number' ? unreviewedCount : 0,\n user: ctx.state.user,\n });\n\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n});\n","import type { Core } from '@strapi/strapi';\n\nconst FIELDS_TO_IGNORE = [\n 'createdAt',\n 'updatedAt',\n 'publishedAt',\n 'createdBy',\n 'updatedBy',\n 'strapi_stage',\n 'strapi_assignee',\n];\n\n/**\n * Builds a recursive Strapi 5 populate tree for deep nested components, relations, and media\n */\nfunction buildHistoryPopulate(\n attributes: Record<string, any>,\n allComponents: Record<string, any>,\n depth = 0\n): Record<string, any> | undefined {\n if (depth > 5) return undefined;\n const populate: Record<string, any> = {};\n\n for (const [key, def] of Object.entries(attributes || {}) as any[]) {\n if (def.type === 'component' && def.component) {\n const comp = allComponents[def.component];\n if (comp?.attributes) {\n const subPopulate = buildHistoryPopulate(comp.attributes, allComponents, depth + 1);\n if (subPopulate && Object.keys(subPopulate).length > 0) {\n populate[key] = {\n populate: subPopulate,\n };\n } else {\n populate[key] = true;\n }\n } else {\n populate[key] = true;\n }\n } else if (def.type === 'dynamiczone') {\n populate[key] = true;\n } else if (def.type === 'relation' || def.type === 'media') {\n populate[key] = true;\n }\n }\n\n return Object.keys(populate).length > 0 ? populate : undefined;\n}\n\nlet cachedAdminUserId: number | null = null;\n\nexport interface ContentHistoryRecordOptions {\n uid: string;\n documentId: string;\n userId?: number | string | null;\n statusOverride?: 'draft' | 'published' | 'modified';\n}\n\n/**\n * Records a Content History version in Strapi's plugin::content-manager.history-version\n * so that any bulk-updated, bulk-published, rolled-back, or CSV-imported record accurately\n * reflects in Strapi's Content History timeline in Content Manager.\n */\nexport async function recordContentHistoryVersion(\n strapi: any,\n options: ContentHistoryRecordOptions\n): Promise<void> {\n const { uid, documentId, userId, statusOverride } = options;\n\n if (!uid || !uid.startsWith('api::') || !documentId) {\n return;\n }\n\n try {\n const historyQuery = strapi.db?.query?.('plugin::content-manager.history-version');\n if (!historyQuery) {\n return;\n }\n\n const model = strapi.getModel?.(uid);\n if (!model) {\n return;\n }\n\n // 1. Fetch updated document state directly via db.query to avoid document service middleware recursion\n let entry: any = null;\n try {\n entry = await strapi.db.query(uid).findOne({\n where: { documentId },\n populate: true,\n });\n } catch {\n try {\n const populateOption = buildHistoryPopulate(model.attributes || {}, strapi.components || {});\n entry = await strapi.documents(uid as any).findOne({\n documentId,\n ...(populateOption ? { populate: populateOption } : {}),\n });\n } catch {\n entry = null;\n }\n }\n\n if (!entry) {\n return;\n }\n\n // 2. Prepare sanitized schema for diff inspection and restore\n const attributesSchema = model.attributes || {};\n const sanitizedSchema = Object.fromEntries(\n Object.entries(attributesSchema).filter(([k]) => !FIELDS_TO_IGNORE.includes(k))\n );\n\n // 3. Prepare sanitized data snapshot\n const sanitizedData = Object.fromEntries(\n Object.entries(entry).filter(([k]) => !FIELDS_TO_IGNORE.includes(k) && k !== 'id')\n );\n\n // 4. Calculate version status\n let status: 'draft' | 'published' | 'modified' = statusOverride || 'published';\n if (!statusOverride) {\n const hasDraftAndPublish = Boolean(model.options?.draftAndPublish);\n if (hasDraftAndPublish) {\n try {\n const docMetaService = strapi.plugin('content-manager')?.service('document-metadata');\n if (docMetaService) {\n const meta = await docMetaService.getMetadata(uid, entry);\n status = docMetaService.getStatus(entry, meta.availableStatus);\n } else {\n status = entry.publishedAt ? 'published' : 'draft';\n }\n } catch {\n status = entry.publishedAt ? 'published' : 'draft';\n }\n } else {\n status = 'published';\n }\n }\n\n // 5. Resolve creator ID\n let authorId = userId;\n if (!authorId) {\n authorId = strapi.requestContext?.get?.()?.state?.user?.id || null;\n }\n let numericUserId = authorId ? Number(authorId) : null;\n if (!numericUserId || isNaN(numericUserId)) {\n if (cachedAdminUserId) {\n numericUserId = cachedAdminUserId;\n } else {\n try {\n const firstAdmin = await strapi.db?.query?.('admin::user')?.findOne?.({ select: ['id'] });\n if (firstAdmin?.id) {\n cachedAdminUserId = Number(firstAdmin.id);\n numericUserId = cachedAdminUserId;\n }\n } catch {}\n }\n }\n\n // 6. Insert record into plugin::content-manager.history-version (strapi_history_versions)\n await historyQuery.create({\n data: {\n contentType: uid,\n relatedDocumentId: documentId,\n locale: entry.locale || null,\n status,\n data: sanitizedData,\n schema: sanitizedSchema,\n createdAt: new Date(),\n ...(numericUserId && !isNaN(numericUserId) ? { createdBy: numericUserId } : {}),\n },\n });\n } catch (err: any) {\n strapi.log?.warn?.(`[bulk-updater] Non-blocking Content History notice for ${uid}/${documentId}: ${err?.message}`);\n }\n}\n\n/**\n * Bulk version recorder: processes an array of document IDs in parallel batches\n */\nexport async function recordContentHistoryVersionsBatch(\n strapi: any,\n items: ContentHistoryRecordOptions[]\n): Promise<void> {\n if (!items || items.length === 0) return;\n const BATCH_SIZE = 10;\n for (let i = 0; i < items.length; i += BATCH_SIZE) {\n const slice = items.slice(i, i + BATCH_SIZE);\n await Promise.all(slice.map((item) => recordContentHistoryVersion(strapi, item)));\n }\n}\n\nexport default {\n recordContentHistoryVersion,\n recordContentHistoryVersionsBatch,\n};\n","import type { Core } from '@strapi/strapi';\nimport crypto from 'crypto';\nimport { recordContentHistoryVersion } from './content-history';\n\n// In-process memory caches (scoped to pod)\ninterface CacheEntry {\n signature: string;\n data: any;\n timestamp: number;\n}\n\nconst queryCache = new Map<string, CacheEntry>();\nconst modelsCache = new Map<string, { signature: string; totalCount: number; entries: any[] }>();\nconst MAX_QUERY_CACHE_SIZE = 500;\nconst CACHE_TTL_MS = 60 * 1000; // 60-second TTL fallback\n\nexport interface RelationMeta {\n isRelation: boolean;\n relationType: string;\n targetUid: string;\n targetDisplayName: string;\n isMulti: boolean;\n}\n\nexport interface AttributeMeta {\n depth: number;\n type: string;\n component?: string;\n isRelation?: boolean;\n}\n\nlet staticSchemaCache: {\n attributes: string[];\n attributesMeta: Record<string, AttributeMeta>;\n targetUids: string[];\n metaByUid: Record<\n string,\n {\n uid: string;\n kind: string;\n isSingleType: boolean;\n singularName: string;\n pluralName: string;\n displayName: string;\n attributes: string[];\n attributesMeta: Record<string, AttributeMeta>;\n relations: Record<string, RelationMeta>;\n }\n >;\n relationsMeta: Record<string, RelationMeta>;\n} | null = null;\n\n/**\n * Ensures consistent two-way mapping for timestamp aliases (updated_at <-> updatedAt,\n * created_at <-> createdAt, published_at <-> publishedAt) so columns in any collection\n * (such as st-feature with updated_at) are properly reflected regardless of source.\n */\nexport function formatEntryRecord(entry: any): any {\n if (!entry || typeof entry !== 'object') return entry;\n const formatted: any = {\n id: entry.id,\n documentId: entry.documentId,\n ...entry,\n };\n if (entry.updatedAt !== undefined && formatted.updated_at === undefined) {\n formatted.updated_at = entry.updatedAt;\n }\n if (entry.updated_at !== undefined && formatted.updatedAt === undefined) {\n formatted.updatedAt = entry.updated_at;\n }\n if (entry.createdAt !== undefined && formatted.created_at === undefined) {\n formatted.created_at = entry.createdAt;\n }\n if (entry.created_at !== undefined && formatted.createdAt === undefined) {\n formatted.createdAt = entry.created_at;\n }\n if (entry.publishedAt !== undefined && formatted.published_at === undefined) {\n formatted.published_at = entry.publishedAt;\n }\n if (entry.published_at !== undefined && formatted.publishedAt === undefined) {\n formatted.publishedAt = entry.published_at;\n }\n return formatted;\n}\n\n/**\n * Resolves a sort or filter field name against a content type schema,\n * checking system timestamps (updatedAt <-> updated_at, createdAt <-> created_at, publishedAt <-> published_at),\n * standard identifiers (id, documentId), and snake_case <-> camelCase attribute variants.\n */\nexport function resolveContentTypeField(contentType: any, field: string): string | null {\n if (!field) return null;\n const attrs = contentType?.attributes || {};\n if (attrs[field]) return field;\n\n // 1. System timestamp & identifier resolution\n if (field === 'updated_at' || field === 'updatedAt') {\n return attrs['updated_at'] ? 'updated_at' : 'updatedAt';\n }\n if (field === 'created_at' || field === 'createdAt') {\n return attrs['created_at'] ? 'created_at' : 'createdAt';\n }\n if (field === 'published_at' || field === 'publishedAt') {\n return attrs['published_at'] ? 'published_at' : 'publishedAt';\n }\n if (field === 'id' || field === 'documentId') {\n return field;\n }\n\n // 2. snake_case -> camelCase\n const camel = field.replace(/_([a-z0-9])/g, (_, l) => l.toUpperCase());\n if (attrs[camel]) return camel;\n\n // 3. camelCase -> snake_case\n const snake = field.replace(/([A-Z])/g, '_$1').toLowerCase();\n if (attrs[snake]) return snake;\n\n // 4. Case-insensitive / underscore-insensitive match across attributes\n const lower = field.toLowerCase().replace(/_/g, '');\n const matched = Object.keys(attrs).find(\n (k) => k.toLowerCase().replace(/_/g, '') === lower\n );\n if (matched) return matched;\n\n return null;\n}\n\n/**\n * Builds a recursive Strapi 5 populate tree for deep nested components, relations, and media\n */\nexport function buildDeepPopulate(\n attributes: Record<string, any>,\n allComponents: Record<string, any>,\n depth = 0\n): Record<string, any> | undefined {\n if (depth > 5) return undefined;\n const populate: Record<string, any> = {};\n\n for (const [key, def] of Object.entries(attributes || {}) as any[]) {\n if (def.type === 'component' && def.component) {\n const comp = allComponents[def.component];\n if (comp?.attributes) {\n const subPopulate = buildDeepPopulate(comp.attributes, allComponents, depth + 1);\n if (subPopulate && Object.keys(subPopulate).length > 0) {\n populate[key] = {\n populate: subPopulate,\n };\n } else {\n populate[key] = true;\n }\n } else {\n populate[key] = true;\n }\n } else if (def.type === 'dynamiczone') {\n populate[key] = {\n populate: '*',\n };\n } else if (def.type === 'relation' || def.type === 'media') {\n populate[key] = true;\n }\n }\n\n return Object.keys(populate).length > 0 ? populate : undefined;\n}\n\n/**\n * Recursively discovers component fields down to a specified maxDepth (up to 5 levels)\n */\nexport function discoverComponentAttributes(\n strapi: any,\n compUid: string,\n prefix: string,\n currentDepth: number,\n maxDepth: number,\n systemFields: string[],\n allContentTypes: Record<string, any>,\n relationsByAttr: Record<string, RelationMeta>,\n allRelationsMeta: Record<string, RelationMeta>,\n attributesMeta: Record<string, AttributeMeta>\n): string[] {\n if (currentDepth > maxDepth || !compUid) return [];\n const compSchema = strapi.components[compUid];\n if (!compSchema?.attributes) return [];\n\n const discoveredAttrs: string[] = [];\n\n for (const [subKey, subAttr] of Object.entries(compSchema.attributes) as any[]) {\n if (systemFields.includes(subKey)) continue;\n const fullPath = prefix ? `${prefix}.${subKey}` : subKey;\n\n if (subAttr.type === 'dynamiczone') {\n const dzComps = Array.isArray(subAttr.components) ? subAttr.components : [];\n for (const dzCompUid of dzComps) {\n const deeper = discoverComponentAttributes(\n strapi,\n dzCompUid,\n fullPath,\n currentDepth + 1,\n maxDepth,\n systemFields,\n allContentTypes,\n relationsByAttr,\n allRelationsMeta,\n attributesMeta\n );\n discoveredAttrs.push(...deeper);\n }\n continue;\n }\n\n if (subAttr.type === 'component') {\n if (subAttr.component) {\n const deeper = discoverComponentAttributes(\n strapi,\n subAttr.component,\n fullPath,\n currentDepth + 1,\n maxDepth,\n systemFields,\n allContentTypes,\n relationsByAttr,\n allRelationsMeta,\n attributesMeta\n );\n discoveredAttrs.push(...deeper);\n }\n } else if (subAttr.type === 'relation') {\n const targetUid = subAttr.target;\n if (targetUid && allContentTypes[targetUid]) {\n const targetInfo = allContentTypes[targetUid]?.info;\n const isMulti = subAttr.relation === 'oneToMany' || subAttr.relation === 'manyToMany';\n const relMeta: RelationMeta = {\n isRelation: true,\n relationType: subAttr.relation,\n targetUid,\n targetDisplayName: targetInfo?.displayName || targetUid,\n isMulti,\n };\n relationsByAttr[fullPath] = relMeta;\n allRelationsMeta[fullPath] = relMeta;\n attributesMeta[fullPath] = { depth: currentDepth, type: 'relation', component: compUid, isRelation: true };\n discoveredAttrs.push(fullPath);\n }\n } else {\n attributesMeta[fullPath] = { depth: currentDepth, type: subAttr.type, component: compUid };\n discoveredAttrs.push(fullPath);\n }\n }\n\n return Array.from(new Set(discoveredAttrs));\n}\n\n/**\n * Parses dynamic zone dot or bracket notation paths:\n * e.g. \"blocks.title\", \"blocks[shared.heading].title\", or \"blocks[0].title\"\n */\nexport function parseDynamicZonePath(path: string): {\n cleanPath: string;\n rootKey: string;\n subPath: string;\n targetComponentUid?: string;\n targetIndex?: number;\n} {\n if (!path) return { cleanPath: '', rootKey: '', subPath: '' };\n const bracketMatch = path.match(/^([^.[]+)\\[([^\\]]+)\\]\\.(.+)$/);\n if (bracketMatch) {\n const rootKey = bracketMatch[1];\n const selector = bracketMatch[2];\n const subPath = bracketMatch[3];\n const cleanPath = `${rootKey}.${subPath}`;\n if (/^\\d+$/.test(selector)) {\n return { cleanPath, rootKey, subPath, targetIndex: parseInt(selector, 10) };\n }\n return { cleanPath, rootKey, subPath, targetComponentUid: selector };\n }\n\n const parts = path.split('.');\n return {\n cleanPath: path,\n rootKey: parts[0] || '',\n subPath: parts.slice(1).join('.'),\n };\n}\n\n/**\n * Formats a component UID into a friendly readable label (e.g. \"shared.featured-section\" -> \"Featured Section\")\n */\nexport function formatComponentName(compUid?: string): string {\n if (!compUid) return 'Component';\n const name = compUid.includes('.') ? compUid.split('.')[1] : compUid;\n return name\n .split(/[-_]/)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(' ');\n}\n\nexport interface DynamicZoneItemMatch {\n index: number;\n componentUid?: string;\n componentName?: string;\n value: any;\n path: string;\n}\n\n/**\n * Extracts all matching instances of a nested property across dynamic zone components or repeatable arrays.\n */\nexport function getAllNestedValues(obj: any, path: string): DynamicZoneItemMatch[] {\n if (!obj || !path) return [];\n const parsed = parseDynamicZonePath(path);\n const parts = parsed.cleanPath.split('.');\n const [head, ...tail] = parts;\n\n const rootTarget = obj[head];\n\n // If rootTarget is an Array (Dynamic Zone or Repeatable Component)\n if (Array.isArray(rootTarget)) {\n const results: DynamicZoneItemMatch[] = [];\n rootTarget.forEach((item, idx) => {\n if (!item || typeof item !== 'object') return;\n if (parsed.targetIndex !== undefined && idx !== parsed.targetIndex) return;\n if (parsed.targetComponentUid && item.__component !== parsed.targetComponentUid) return;\n\n const compSchema = (global as any).strapi?.components?.[item.__component];\n const fieldInSchema = tail.length > 0 && compSchema?.attributes\n ? tail[0] in compSchema.attributes\n : false;\n\n const subVal = tail.length > 0 ? getDeepProperty(item, tail.join('.')) : item;\n if (subVal !== undefined || fieldInSchema) {\n results.push({\n index: idx,\n componentUid: item.__component,\n componentName: formatComponentName(item.__component),\n value: subVal !== undefined ? subVal : null,\n path: `${head}[#${idx}${item.__component ? ` ${formatComponentName(item.__component)}` : ''}].${tail.join('.')}`,\n });\n }\n });\n return results;\n }\n\n // Not an array, standard object resolution\n const singleVal = getDeepProperty(obj, parsed.cleanPath);\n if (singleVal !== undefined) {\n return [\n {\n index: 0,\n value: singleVal,\n path: parsed.cleanPath,\n },\n ];\n }\n\n return [];\n}\n\n/**\n * Validates whether an attribute corresponds to a valid deep component hierarchy\n */\nexport function isDeepComponentField(contentType: any, allComponents: Record<string, any>, attribute: string): boolean {\n if (!attribute || (!attribute.includes('.') && !attribute.includes('['))) return false;\n const parsed = parseDynamicZonePath(attribute);\n const parts = parsed.cleanPath.split('.');\n\n function checkPath(currentSchema: any, pathParts: string[]): boolean {\n if (pathParts.length === 0) return true;\n if (!currentSchema || !currentSchema.attributes) return false;\n const [head, ...tail] = pathParts;\n const attrDef = currentSchema.attributes[head];\n if (!attrDef) return false;\n\n if (tail.length === 0) {\n return true;\n }\n\n if (attrDef.type === 'component' && attrDef.component) {\n const comp = allComponents[attrDef.component];\n return checkPath(comp, tail);\n }\n\n if (attrDef.type === 'dynamiczone') {\n const compUids = Array.isArray(attrDef.components) ? attrDef.components : [];\n if (parsed.targetComponentUid) {\n const comp = allComponents[parsed.targetComponentUid];\n return comp ? checkPath(comp, tail) : false;\n }\n return compUids.some((compUid: string) => {\n const comp = allComponents[compUid];\n return checkPath(comp, tail);\n });\n }\n\n return false;\n }\n\n return checkPath(contentType, parts);\n}\n\n/**\n * Retrieves the schema definition of a leaf attribute from a deep dot-notation or bracket path\n */\nexport function getLeafAttributeSchema(contentType: any, allComponents: Record<string, any>, attribute: string): any {\n if (!attribute) return null;\n const parsed = parseDynamicZonePath(attribute);\n if (!parsed.cleanPath.includes('.')) return contentType?.attributes?.[parsed.cleanPath] || null;\n const parts = parsed.cleanPath.split('.');\n\n function resolveLeaf(currentSchema: any, pathParts: string[]): any {\n if (!currentSchema || !currentSchema.attributes) return null;\n const [head, ...tail] = pathParts;\n const attrDef = currentSchema.attributes[head];\n if (!attrDef) return null;\n\n if (tail.length === 0) {\n return attrDef;\n }\n\n if (attrDef.type === 'component' && attrDef.component) {\n return resolveLeaf(allComponents[attrDef.component], tail);\n }\n\n if (attrDef.type === 'dynamiczone') {\n const compUids = Array.isArray(attrDef.components) ? attrDef.components : [];\n if (parsed.targetComponentUid) {\n return resolveLeaf(allComponents[parsed.targetComponentUid], tail);\n }\n for (const compUid of compUids) {\n const found = resolveLeaf(allComponents[compUid], tail);\n if (found) return found;\n }\n }\n\n return null;\n }\n\n return resolveLeaf(contentType, parts);\n}\n\n/**\n * Immutably sets a nested property at an arbitrary depth while preserving all sibling properties.\n * Fully supports selective targeting of specific dynamic zone indices or component types.\n */\nexport function setDeepProperty(\n obj: any,\n pathParts: string[],\n value: any,\n options?: {\n targetIndexes?: number[];\n targetComponentUid?: string;\n }\n): any {\n if (pathParts.length === 0) return value;\n const [head, ...tail] = pathParts;\n\n // Case 1: If current obj is an Array (e.g. Dynamic Zone or Repeatable Component)\n if (Array.isArray(obj)) {\n // If head is a numeric index, update only that specific index\n if (/^\\d+$/.test(head)) {\n const idx = parseInt(head, 10);\n const copy = [...obj];\n copy[idx] = setDeepProperty(copy[idx] || {}, tail, value, options);\n return copy;\n }\n\n // Otherwise, head is a property name inside the array items!\n // Update items according to options.targetIndexes / options.targetComponentUid\n return obj.map((item, idx) => {\n if (!item || typeof item !== 'object') return item;\n\n if (options?.targetIndexes && options.targetIndexes.length > 0) {\n if (!options.targetIndexes.includes(idx)) return item;\n }\n\n if (options?.targetComponentUid) {\n if (item.__component !== options.targetComponentUid) return item;\n }\n\n const compSchema = (global as any).strapi?.components?.[item.__component];\n const fieldExistsInSchema = compSchema?.attributes ? head in compSchema.attributes : true;\n\n if (head in item || fieldExistsInSchema || tail.length === 0) {\n return {\n ...item,\n [head]: setDeepProperty(item[head], tail, value, options),\n };\n }\n return item;\n });\n }\n\n // Case 2: obj is an Object\n const current = { ...(obj || {}) };\n if (tail.length === 0) {\n current[head] = value;\n } else {\n const subTarget = current[head];\n if (Array.isArray(subTarget)) {\n current[head] = setDeepProperty(subTarget, tail, value, options);\n } else {\n current[head] = setDeepProperty(subTarget || {}, tail, value, options);\n }\n }\n return current;\n}\n\n/**\n * Safely resolves a nested dot-notation property (e.g. \"a.b.c.d\" or bracket notation) across objects and dynamic zone arrays\n */\nexport function getDeepProperty(obj: any, path: string): any {\n if (!obj || !path) return undefined;\n const parsed = parseDynamicZonePath(path);\n const parts = parsed.cleanPath.split('.');\n\n function extract(current: any, remainingParts: string[]): any {\n if (current === undefined || current === null) return undefined;\n if (remainingParts.length === 0) return current;\n\n const [head, ...tail] = remainingParts;\n\n if (Array.isArray(current)) {\n if (/^\\d+$/.test(head)) {\n return extract(current[parseInt(head, 10)], tail);\n }\n for (let idx = 0; idx < current.length; idx++) {\n const item = current[idx];\n if (parsed.targetIndex !== undefined && idx !== parsed.targetIndex) continue;\n if (parsed.targetComponentUid && item?.__component !== parsed.targetComponentUid) continue;\n const found = extract(item?.[head], tail);\n if (found !== undefined && found !== null) return found;\n }\n return undefined;\n }\n\n return extract(current[head], tail);\n }\n\n return extract(obj, parts);\n}\n\n/**\n * Constructs a nested filter object for Strapi 5 Document queries (e.g. { a: { b: { c: condition } } })\n */\nexport function buildDeepFilter(pathParts: string[], condition: any): any {\n if (pathParts.length === 0) return condition;\n const [head, ...tail] = pathParts;\n return {\n [head]: buildDeepFilter(tail, condition),\n };\n}\n\nexport interface ExecutionWindowConfig {\n enabled: boolean;\n timeZone: string;\n businessHours: {\n start: string;\n end: string;\n };\n offPeakStartTime: string;\n autoQueueDuringBusinessHours: boolean;\n}\n\nexport function getSafeTimezone(timeZone?: string): string {\n if (!timeZone || typeof timeZone !== 'string') {\n return Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';\n }\n try {\n Intl.DateTimeFormat(undefined, { timeZone: timeZone.trim() });\n return timeZone.trim();\n } catch {\n return 'UTC';\n }\n}\n\nexport function getTimeInTimezone(timeZone: string, date: Date = new Date()): { hours: number; minutes: number; timeString: string } {\n const safeTz = getSafeTimezone(timeZone);\n const formatter = new Intl.DateTimeFormat('en-GB', {\n timeZone: safeTz,\n hour: '2-digit',\n minute: '2-digit',\n hourCycle: 'h23',\n });\n const timeString = formatter.format(date);\n const [h, m] = timeString.split(':').map(Number);\n return { hours: h, minutes: m, timeString };\n}\n\nexport function getExecutionWindowConfig(strapi: Core.Strapi): ExecutionWindowConfig {\n const pluginConfig = strapi.config.get('plugin::bulk-updater.executionWindow') as Partial<ExecutionWindowConfig> | undefined;\n const configuredTz = pluginConfig?.timeZone ||\n strapi.config.get('server.timeZone') ||\n Intl.DateTimeFormat().resolvedOptions().timeZone ||\n 'UTC';\n const timeZone = getSafeTimezone(configuredTz);\n\n return {\n enabled: pluginConfig?.enabled ?? true,\n timeZone,\n businessHours: {\n start: pluginConfig?.businessHours?.start || '09:00',\n end: pluginConfig?.businessHours?.end || '18:00',\n },\n offPeakStartTime: pluginConfig?.offPeakStartTime || '18:00',\n autoQueueDuringBusinessHours: pluginConfig?.autoQueueDuringBusinessHours ?? true,\n };\n}\n\nexport function checkBusinessHours(config: ExecutionWindowConfig, testDate?: Date) {\n const timeZone = getSafeTimezone(config.timeZone);\n const { hours, minutes, timeString } = getTimeInTimezone(timeZone, testDate || new Date());\n\n const currentMinutes = hours * 60 + minutes;\n const [startH, startM] = (config.businessHours.start || '09:00').split(':').map(Number);\n const [endH, endM] = (config.businessHours.end || '18:00').split(':').map(Number);\n const startMinutes = startH * 60 + startM;\n const endMinutes = endH * 60 + endM;\n\n const isBusinessHours = currentMinutes >= startMinutes && currentMinutes < endMinutes;\n\n return {\n isBusinessHours,\n currentServerTime: timeString,\n timeZone,\n businessHours: config.businessHours,\n offPeakStartTime: config.offPeakStartTime,\n policyMessage: isBusinessHours\n ? `Server policy restricts bulk updates during peak business hours (${config.businessHours.start} - ${config.businessHours.end} ${timeZone}). Current time: ${timeString} (${timeZone}). Updates will be queued for off-peak execution at ${config.offPeakStartTime} ${timeZone}.`\n : `Currently in off-peak execution window (outside ${config.businessHours.start} - ${config.businessHours.end} ${timeZone}). Current time: ${timeString} (${timeZone}). Direct execution is permitted.`,\n };\n}\n\nexport interface PendingBatch {\n id: string;\n createdAt: string;\n createdBy: { id?: string | number; email?: string; firstname?: string; lastname?: string; username?: string };\n payload: {\n action?: string;\n attribute: string;\n value: string;\n selectedEntries?: Array<{ uid: string; documentId: string; dynamicZoneIndexes?: number[]; targetComponentUid?: string }>;\n selectedCollections?: string[];\n isRegex?: boolean;\n regexPattern?: string;\n publishOnApproval?: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n unreviewedCount?: number;\n rows?: any[];\n uid?: string;\n options?: any;\n };\n summary: {\n attribute: string;\n value: string;\n totalTargets: number;\n collectionBreakdown: Record<string, number>;\n publishOnApproval?: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n unreviewedCount?: number;\n };\n status: 'pending_approval' | 'queued_offpeak' | 'approved' | 'rejected' | 'executed';\n executionMode: 'maker_checker' | 'queue_offpeak' | 'immediate';\n scheduledFor?: string;\n makerNotes?: string;\n approval?: {\n checkerUser?: { id?: string | number; email?: string; firstname?: string; lastname?: string; username?: string };\n decisionDate?: string;\n rejectionReason?: string;\n };\n executionResult?: any;\n}\n\nexport interface BatchJobState {\n id: string;\n createdAt: string;\n startedAt?: string;\n completedAt?: string;\n createdBy: { id?: string | number; email?: string; firstname?: string; lastname?: string; username?: string };\n status: 'pending_approval' | 'queued_offpeak' | 'processing' | 'successful' | 'partial_failure' | 'failed';\n executionMode: 'immediate' | 'maker_checker' | 'queue_offpeak';\n scheduledFor?: string;\n attribute: string;\n value: string;\n totalTargets: number;\n processedCount: number;\n updatedCount: number;\n skippedCount: number;\n failedCount: number;\n isLive: boolean;\n publishOnApproval: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n unreviewedCount?: number;\n policyMessage?: string;\n makerNotes?: string;\n results: Array<{\n uid: string;\n collectionName: string;\n documentId: string;\n label: string;\n attribute: string;\n oldValue: any;\n newValue: any;\n status: 'updated' | 'skipped' | 'error';\n message: string;\n isLive?: boolean;\n }>;\n error?: string;\n}\n\nconst pendingBatches = new Map<string, PendingBatch>();\nconst batchJobsMap = new Map<string, BatchJobState>();\nlet isRunnerRunning = false;\nlet runnerInterval: NodeJS.Timeout | null = null;\n\nexport function registerPendingBatch(batch: PendingBatch, jobState?: BatchJobState) {\n pendingBatches.set(batch.id, batch);\n if (jobState) {\n batchJobsMap.set(batch.id, jobState);\n }\n}\n\nexport function invalidateCollectionCache(uid: string) {\n modelsCache.delete(uid);\n for (const key of queryCache.keys()) {\n if (key.startsWith(`${uid}:`)) {\n queryCache.delete(key);\n }\n }\n}\n\nasync function getCollectionSignature(strapi: Core.Strapi, uid: string): Promise<string> {\n const contentType = strapi.contentTypes[uid];\n if (!contentType) return 'invalid';\n\n const isSingleType = contentType.kind === 'singleType';\n try {\n if (isSingleType) {\n const doc: any = await (strapi.documents(uid as any) as any).findFirst({\n fields: ['updatedAt', 'id'],\n });\n return doc ? `single:${doc.id}:${doc.updatedAt}` : 'single:empty';\n }\n\n const [total, latest] = await Promise.all([\n strapi.documents(uid as any).count(),\n strapi.documents(uid as any).findMany({\n limit: 1,\n sort: { updatedAt: 'desc' },\n fields: ['updatedAt', 'id'],\n }),\n ]);\n\n const latestDoc = latest && latest.length > 0 ? latest[0] : null;\n return `${total}:${latestDoc?.updatedAt || '0'}:${latestDoc?.id || '0'}`;\n } catch {\n return `${Date.now()}`;\n }\n}\n\nasync function computeTargetsSummary(strapi: Core.Strapi, { selectedCollections = [], selectedEntries = [] }: any) {\n const targetsMap = new Map<string, { uid: string; documentId: string }>();\n const breakdown: Record<string, number> = {};\n\n for (const colUid of selectedCollections) {\n const contentType = strapi.contentTypes[colUid];\n const displayName = contentType?.info?.displayName || colUid;\n try {\n const entries = await strapi.documents(colUid as any).findMany();\n const count = entries ? entries.length : 0;\n breakdown[displayName] = (breakdown[displayName] || 0) + count;\n for (const entry of (entries || []) as any[]) {\n targetsMap.set(`${colUid}@@@${entry.documentId}`, { uid: colUid, documentId: entry.documentId });\n }\n } catch {\n // Ignore count failures\n }\n }\n\n for (const item of selectedEntries) {\n if (!item.uid || !item.documentId) continue;\n const key = `${item.uid}@@@${item.documentId}`;\n if (!targetsMap.has(key)) {\n targetsMap.set(key, { uid: item.uid, documentId: item.documentId });\n const contentType = strapi.contentTypes[item.uid];\n const displayName = contentType?.info?.displayName || item.uid;\n breakdown[displayName] = (breakdown[displayName] || 0) + 1;\n }\n }\n\n return {\n totalTargets: targetsMap.size,\n collectionBreakdown: breakdown,\n };\n}\n\nasync function executeBatchInternal(\n strapi: Core.Strapi,\n {\n attribute,\n value,\n selectedEntries = [],\n selectedCollections = [],\n isRegex = false,\n regexPattern = '',\n publishOnApproval = true,\n publishStrategy = 'safe',\n unreviewedConsent = false,\n }: {\n attribute: string;\n value: string;\n selectedEntries?: Array<{ uid: string; documentId: string; dynamicZoneIndexes?: number[]; targetComponentUid?: string }>;\n selectedCollections?: string[];\n isRegex?: boolean;\n regexPattern?: string;\n publishOnApproval?: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n },\n currentUser?: any,\n existingBatchId?: string\n) {\n if (!attribute) {\n throw new Error('Attribute name is required.');\n }\n\n const targetsMap = new Map<string, { uid: string; documentId: string; dynamicZoneIndexes?: number[]; targetComponentUid?: string }>();\n\n // 1. Add entire collections if selected\n for (const colUid of selectedCollections) {\n if (!strapi.contentTypes[colUid]) continue;\n const entries = await strapi.documents(colUid as any).findMany();\n for (const entry of (entries || []) as any[]) {\n const key = `${colUid}@@@${entry.documentId}`;\n targetsMap.set(key, { uid: colUid, documentId: entry.documentId });\n }\n }\n\n // 2. Add individually selected entries\n for (const item of selectedEntries) {\n if (!item.uid || !item.documentId) continue;\n const key = `${item.uid}@@@${item.documentId}`;\n targetsMap.set(key, {\n uid: item.uid,\n documentId: item.documentId,\n dynamicZoneIndexes: item.dynamicZoneIndexes,\n targetComponentUid: item.targetComponentUid,\n });\n }\n\n if (targetsMap.size === 0) {\n throw new Error('No collections or entries were selected for update.');\n }\n\n const batchId = existingBatchId || `batch_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const results: any[] = [];\n let updatedCount = 0;\n let skippedCount = 0;\n\n const jobState: BatchJobState = {\n id: batchId,\n createdAt: new Date().toISOString(),\n startedAt: new Date().toISOString(),\n createdBy: currentUser\n ? {\n id: currentUser.id,\n email: currentUser.email,\n firstname: currentUser.firstname,\n lastname: currentUser.lastname,\n username: currentUser.username,\n }\n : { email: 'admin@system.local' },\n status: 'processing',\n executionMode: 'immediate',\n attribute,\n value,\n totalTargets: targetsMap.size,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: Boolean(publishOnApproval),\n publishStrategy,\n unreviewedConsent,\n results: [],\n };\n batchJobsMap.set(batchId, jobState);\n\n let regexObj: RegExp | null = null;\n if (isRegex && regexPattern) {\n regexObj = new RegExp(regexPattern, 'g');\n }\n\n const targets = Array.from(targetsMap.values());\n const CHUNK_SIZE = 25; // 25 concurrent updates per batch window\n\n // Request-scoped DataLoader for deduplicating lookups during batch itemization\n const documentLoader = new Map<string, Promise<any>>();\n const getDocumentDeduplicated = (uid: string, documentId: string) => {\n const loaderKey = `${uid}@@@${documentId}`;\n if (!documentLoader.has(loaderKey)) {\n documentLoader.set(\n loaderKey,\n strapi.documents(uid as any).findOne({ documentId })\n );\n }\n return documentLoader.get(loaderKey);\n };\n\n for (let i = 0; i < targets.length; i += CHUNK_SIZE) {\n const chunk = targets.slice(i, i + CHUNK_SIZE);\n const chunkPromises = chunk.map(async (target) => {\n const contentType = strapi.contentTypes[target.uid];\n const displayName = contentType?.info?.displayName || target.uid;\n\n try {\n const currentEntry: any = await getDocumentDeduplicated(target.uid, target.documentId);\n\n const entryLabel =\n currentEntry?.name ||\n currentEntry?.title ||\n currentEntry?.email ||\n `Entry #${target.documentId}`;\n\n const parsed = parseDynamicZonePath(attribute);\n const isNested = attribute.includes('.') || attribute.includes('[');\n const isComponentNested = isNested && isDeepComponentField(contentType, strapi.components, attribute);\n const parts = isNested ? parsed.cleanPath.split('.') : [];\n const rootKey = parsed.rootKey;\n const targetComponentUid = target.targetComponentUid || parsed.targetComponentUid;\n const targetIndexes = target.dynamicZoneIndexes;\n\n const attrDef = contentType?.attributes?.[attribute];\n const hasAttribute = Boolean(attrDef) || isComponentNested;\n\n if (hasAttribute) {\n if (isComponentNested) {\n // Retrieve current component state with deep populate for safe recursive merge\n const populateOption = buildDeepPopulate(contentType.attributes, strapi.components);\n const findOneArgs: any = { documentId: target.documentId };\n if (populateOption) {\n findOneArgs.populate = populateOption;\n }\n const currentEntryWithPopulate: any = await strapi.documents(target.uid as any).findOne(findOneArgs);\n const isRootDz = contentType?.attributes?.[rootKey]?.type === 'dynamiczone';\n const existingRoot = currentEntryWithPopulate?.[rootKey] || (isRootDz ? [] : {});\n\n let affectedMatches: DynamicZoneItemMatch[] = [];\n if (isRootDz && Array.isArray(existingRoot)) {\n affectedMatches = getAllNestedValues({ [rootKey]: existingRoot }, attribute);\n if (targetIndexes && targetIndexes.length > 0) {\n affectedMatches = affectedMatches.filter((m) => targetIndexes.includes(m.index));\n }\n if (targetComponentUid) {\n affectedMatches = affectedMatches.filter((m) => m.componentUid === targetComponentUid);\n }\n }\n\n const currentVal = isRootDz\n ? (affectedMatches.length > 0 ? affectedMatches.map((m) => m.value).join(', ') : getDeepProperty(existingRoot, parts.slice(1).join('.')))\n : getDeepProperty(existingRoot, parts.slice(1).join('.'));\n\n let newValue = value;\n if (regexObj && typeof currentVal === 'string') {\n newValue = currentVal.replace(regexObj, value);\n }\n\n const updatedRoot = setDeepProperty(existingRoot, parts.slice(1), newValue, {\n targetIndexes,\n targetComponentUid,\n });\n\n await strapi.documents(target.uid as any).update({\n documentId: target.documentId,\n data: {\n [rootKey]: updatedRoot,\n },\n });\n\n // If publishOnApproval is true and content type has draftAndPublish enabled, publish the document\n const isDraftAndPublishComp = Boolean(contentType?.options?.draftAndPublish);\n const isApprovedComp = isDraftAndPublishComp && Boolean(currentEntry?.publishedAt) && currentEntry?.status !== 'modified';\n const shouldPublishComp = isDraftAndPublishComp && Boolean(publishOnApproval) && (\n publishStrategy === 'all' ? true : isApprovedComp\n );\n if (shouldPublishComp) {\n try {\n await (strapi.documents(target.uid as any) as any).publish({\n documentId: target.documentId,\n });\n } catch (publishErr) {\n strapi.log.warn(`[bulk-updater] Failed to auto-publish ${target.uid}/${target.documentId}:`, publishErr);\n }\n }\n\n invalidateCollectionCache(target.uid);\n\n await recordContentHistoryVersion(strapi, {\n uid: target.uid,\n documentId: target.documentId,\n userId: currentUser?.id,\n statusOverride: shouldPublishComp ? 'published' : (isDraftAndPublishComp ? 'draft' : undefined),\n });\n\n const dzDiffs = isRootDz && affectedMatches.length > 0\n ? affectedMatches.map((m) => ({\n index: m.index,\n componentUid: m.componentUid,\n componentName: m.componentName,\n attribute: `${rootKey}[#${m.index} ${m.componentName}].${parts.slice(1).join('.')}`,\n oldValue: m.value,\n newValue: regexObj && typeof m.value === 'string' ? m.value.replace(regexObj, value) : value,\n }))\n : [];\n\n return {\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: entryLabel,\n attribute,\n oldValue: currentVal ?? null,\n newValue,\n status: 'updated' as const,\n message: isRootDz\n ? `Successfully updated ${affectedMatches.length} dynamic zone item(s) in ${attribute}`\n : `Successfully updated nested field ${attribute}`,\n dynamicZoneDiffs: dzDiffs,\n };\n }\n\n if (attrDef.type === 'relation') {\n const isMulti = attrDef.relation === 'oneToMany' || attrDef.relation === 'manyToMany';\n\n // Retrieve current relation state with populate for accurate audit logging\n const currentEntryWithPopulate: any = await strapi.documents(target.uid as any).findOne({\n documentId: target.documentId,\n populate: [attribute],\n });\n const currentRel = currentEntryWithPopulate?.[attribute];\n\n let oldDocIds: string[] = [];\n let oldDisplay = '';\n if (isMulti && Array.isArray(currentRel)) {\n oldDocIds = currentRel.map((r: any) => r.documentId).filter(Boolean);\n oldDisplay = currentRel.map((r: any) => r.name || r.title || r.email || r.documentId).join(', ') || '(empty)';\n } else if (currentRel) {\n oldDocIds = currentRel.documentId ? [currentRel.documentId] : [];\n oldDisplay = currentRel.name || currentRel.title || currentRel.email || currentRel.documentId || '(empty)';\n } else {\n oldDisplay = '(unlinked / none)';\n }\n\n // Parse relation command:\n let mode: 'set' | 'connect' | 'disconnect' | 'clear' = 'set';\n let targetDocIds: string[] = [];\n let newDisplay = '';\n\n if (value === '__clear__' || value === '') {\n mode = 'clear';\n newDisplay = '(cleared / unlinked)';\n } else {\n try {\n const parsed = JSON.parse(value);\n if (parsed && typeof parsed === 'object' && parsed.mode) {\n mode = parsed.mode;\n targetDocIds = Array.isArray(parsed.documentIds) ? parsed.documentIds : (parsed.documentId ? [parsed.documentId] : []);\n newDisplay = parsed.label || targetDocIds.join(', ') || `[${mode}]`;\n } else if (Array.isArray(parsed)) {\n targetDocIds = parsed;\n newDisplay = targetDocIds.join(', ');\n } else {\n targetDocIds = [value];\n newDisplay = value;\n }\n } catch {\n targetDocIds = [value];\n newDisplay = value;\n }\n }\n\n // Construct Document Service relation mutation payload\n let relationPayload: any;\n if (mode === 'clear') {\n relationPayload = isMulti ? { set: [] } : null;\n } else if (mode === 'set') {\n relationPayload = isMulti ? { set: targetDocIds } : (targetDocIds[0] || null);\n } else if (mode === 'connect') {\n relationPayload = { connect: targetDocIds };\n } else if (mode === 'disconnect') {\n relationPayload = { disconnect: targetDocIds };\n }\n\n await strapi.documents(target.uid as any).update({\n documentId: target.documentId,\n data: {\n [attribute]: relationPayload,\n },\n });\n\n // If publishOnApproval is true and content type has draftAndPublish enabled, publish the document\n const isDraftAndPublishRel = Boolean(contentType?.options?.draftAndPublish);\n const isApprovedRel = isDraftAndPublishRel && Boolean(currentEntry?.publishedAt) && currentEntry?.status !== 'modified';\n const shouldPublishRel = isDraftAndPublishRel && Boolean(publishOnApproval) && (\n publishStrategy === 'all' ? true : isApprovedRel\n );\n if (shouldPublishRel) {\n try {\n await (strapi.documents(target.uid as any) as any).publish({\n documentId: target.documentId,\n });\n } catch (publishErr) {\n strapi.log.warn(`[bulk-updater] Failed to auto-publish ${target.uid}/${target.documentId}:`, publishErr);\n }\n }\n\n invalidateCollectionCache(target.uid);\n if (attrDef.target) {\n invalidateCollectionCache(attrDef.target);\n }\n\n await recordContentHistoryVersion(strapi, {\n uid: target.uid,\n documentId: target.documentId,\n userId: currentUser?.id,\n statusOverride: shouldPublishRel ? 'published' : (isDraftAndPublishRel ? 'draft' : undefined),\n });\n\n return {\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: entryLabel,\n attribute,\n oldValue: { isRelation: true, documentIds: oldDocIds, display: oldDisplay },\n newValue: { isRelation: true, mode, documentIds: targetDocIds, display: newDisplay },\n status: 'updated' as const,\n message: `Successfully updated relation \"${attribute}\"`,\n };\n }\n\n let newValue = value;\n const currentVal = currentEntry?.[attribute];\n\n if (regexObj && typeof currentVal === 'string') {\n newValue = currentVal.replace(regexObj, value);\n }\n\n await strapi.documents(target.uid as any).update({\n documentId: target.documentId,\n data: {\n [attribute]: newValue,\n },\n });\n\n // If publishOnApproval is true and content type has draftAndPublish enabled, publish the document\n const isDraftAndPublishScalar = Boolean(contentType?.options?.draftAndPublish);\n const isApprovedScalar = isDraftAndPublishScalar && Boolean(currentEntry?.publishedAt) && currentEntry?.status !== 'modified';\n const shouldPublishScalar = isDraftAndPublishScalar && Boolean(publishOnApproval) && (\n publishStrategy === 'all' ? true : isApprovedScalar\n );\n if (shouldPublishScalar) {\n try {\n await (strapi.documents(target.uid as any) as any).publish({\n documentId: target.documentId,\n });\n } catch (publishErr) {\n strapi.log.warn(`[bulk-updater] Failed to auto-publish ${target.uid}/${target.documentId}:`, publishErr);\n }\n }\n\n await recordContentHistoryVersion(strapi, {\n uid: target.uid,\n documentId: target.documentId,\n userId: currentUser?.id,\n statusOverride: shouldPublishScalar ? 'published' : (isDraftAndPublishScalar ? 'draft' : undefined),\n });\n\n return {\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: entryLabel,\n attribute,\n oldValue: currentVal ?? null,\n newValue,\n status: 'updated' as const,\n message: `Successfully updated ${attribute}`,\n };\n } else {\n return {\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: entryLabel,\n attribute,\n status: 'skipped' as const,\n message: `Skipped: Attribute \"${attribute}\" does not exist in schema for ${displayName}`,\n };\n }\n } catch (updateErr: any) {\n return {\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: `Entry #${target.documentId}`,\n attribute,\n status: 'error' as const,\n message: updateErr.message,\n };\n }\n });\n\n const chunkResults = await Promise.all(chunkPromises);\n for (const res of chunkResults) {\n if (res.status === 'updated') updatedCount++;\n else if (res.status === 'skipped') skippedCount++;\n results.push(res);\n }\n jobState.processedCount = results.length;\n jobState.updatedCount = updatedCount;\n jobState.skippedCount = skippedCount;\n jobState.failedCount = results.filter((r) => r.status === 'error').length;\n }\n\n // Invalidate local in-process cache for all affected collection UIDs\n const affectedUids = new Set(targets.map((t) => t.uid));\n affectedUids.forEach((uid) => {\n invalidateCollectionCache(uid);\n });\n\n const failedCount = results.filter((r) => r.status === 'error').length;\n jobState.failedCount = failedCount;\n jobState.completedAt = new Date().toISOString();\n jobState.isLive = updatedCount > 0;\n jobState.status =\n failedCount === 0 && updatedCount > 0\n ? 'successful'\n : failedCount > 0 && updatedCount > 0\n ? 'partial_failure'\n : failedCount > 0\n ? 'failed'\n : 'successful';\n jobState.results = results.map((r) => ({\n ...r,\n isLive: r.status === 'updated',\n }));\n\n const flattenedDiffs: any[] = [];\n for (const r of results) {\n if (r.dynamicZoneDiffs && r.dynamicZoneDiffs.length > 0) {\n for (const dz of r.dynamicZoneDiffs) {\n flattenedDiffs.push({\n uid: r.uid,\n collectionName: r.collectionName,\n documentId: r.documentId,\n label: `${r.label} [Block #${dz.index} (${dz.componentName})]`,\n attribute: dz.attribute,\n oldValue: dz.oldValue,\n newValue: dz.newValue,\n status: 'updated',\n message: `Updated ${dz.attribute}`,\n });\n }\n } else {\n flattenedDiffs.push(r);\n }\n }\n\n const batchSummary = {\n batchId,\n attribute,\n value,\n updatedCount,\n skippedCount,\n totalTargets: targetsMap.size,\n publishOnApproval,\n publishStrategy,\n unreviewedConsent,\n };\n\n // Stateless audit recording via consumer's declared audit schema\n await strapi.plugin('bulk-updater').service('audit').recordBatch(\n batchSummary,\n flattenedDiffs,\n currentUser\n );\n\n return {\n success: true,\n batchId,\n attribute,\n value,\n updatedCount,\n skippedCount,\n failedCount,\n totalTargets: targetsMap.size,\n isLive: jobState.isLive,\n status: jobState.status,\n results,\n };\n}\n\n/**\n * Executes a bulk publish operation directly across selected entries and collections.\n */\nasync function executePublishBatchInternal(\n strapi: Core.Strapi,\n {\n selectedEntries = [],\n selectedCollections = [],\n unreviewedConsent = false,\n }: {\n selectedEntries?: Array<{ uid: string; documentId: string }>;\n selectedCollections?: string[];\n unreviewedConsent?: boolean;\n },\n currentUser?: any,\n existingBatchId?: string\n) {\n const targetsMap = new Map<string, { uid: string; documentId: string }>();\n\n // 1. Add entire collections if selected\n for (const colUid of selectedCollections) {\n if (!strapi.contentTypes[colUid]) continue;\n const entries = await (strapi.documents(colUid as any) as any).findMany();\n for (const entry of (entries || []) as any[]) {\n const key = `${colUid}@@@${entry.documentId}`;\n targetsMap.set(key, { uid: colUid, documentId: entry.documentId });\n }\n }\n\n // 2. Add individually selected entries\n for (const item of selectedEntries) {\n if (!item.uid || !item.documentId) continue;\n const key = `${item.uid}@@@${item.documentId}`;\n targetsMap.set(key, { uid: item.uid, documentId: item.documentId });\n }\n\n if (targetsMap.size === 0) {\n throw new Error('No collections or entries were selected to publish.');\n }\n\n const batchId = existingBatchId || `batch_pub_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const results: any[] = [];\n let publishedCount = 0;\n let skippedCount = 0;\n\n const jobState: BatchJobState = {\n id: batchId,\n createdAt: new Date().toISOString(),\n startedAt: new Date().toISOString(),\n createdBy: currentUser\n ? {\n id: currentUser.id,\n email: currentUser.email,\n firstname: currentUser.firstname,\n lastname: currentUser.lastname,\n username: currentUser.username,\n }\n : { email: 'admin@system.local' },\n status: 'processing',\n executionMode: 'immediate',\n attribute: '(publish)',\n value: 'published',\n totalTargets: targetsMap.size,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: true,\n unreviewedConsent,\n results: [],\n };\n batchJobsMap.set(batchId, jobState);\n\n const targets = Array.from(targetsMap.values());\n const CHUNK_SIZE = 25;\n\n for (let i = 0; i < targets.length; i += CHUNK_SIZE) {\n const chunk = targets.slice(i, i + CHUNK_SIZE);\n\n const chunkPromises = chunk.map(async (target) => {\n try {\n const contentType = strapi.contentTypes[target.uid];\n const displayName = contentType?.info?.displayName || target.uid;\n const isDraftAndPublish = Boolean(contentType?.options?.draftAndPublish);\n\n let existingDoc: any = null;\n try {\n existingDoc = await (strapi.documents(target.uid as any) as any).findOne({\n documentId: target.documentId,\n });\n } catch {\n existingDoc = null;\n }\n\n const entryLabel =\n existingDoc?.name ||\n existingDoc?.title ||\n existingDoc?.label ||\n existingDoc?.documentId ||\n `Entry #${target.documentId}`;\n\n if (!isDraftAndPublish) {\n return {\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: entryLabel,\n attribute: '(publish)',\n status: 'skipped' as const,\n message: `Skipped: Draft & Publish is disabled for collection ${displayName}`,\n };\n }\n\n const isAlreadyPublished = Boolean(existingDoc?.publishedAt);\n\n await (strapi.documents(target.uid as any) as any).publish({\n documentId: target.documentId,\n });\n\n invalidateCollectionCache(target.uid);\n\n await recordContentHistoryVersion(strapi, {\n uid: target.uid,\n documentId: target.documentId,\n userId: currentUser?.id,\n statusOverride: 'published',\n });\n\n return {\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: entryLabel,\n attribute: '(publish)',\n oldValue: isAlreadyPublished ? 'published' : 'draft',\n newValue: 'published',\n status: 'updated' as const,\n message: isAlreadyPublished\n ? 'Re-published latest version live'\n : 'Successfully published to live',\n };\n } catch (pubErr: any) {\n return {\n uid: target.uid,\n collectionName: strapi.contentTypes[target.uid]?.info?.displayName || target.uid,\n documentId: target.documentId,\n label: `Entry #${target.documentId}`,\n attribute: '(publish)',\n status: 'error' as const,\n message: pubErr.message || 'Failed to publish entry',\n };\n }\n });\n\n const chunkResults = await Promise.all(chunkPromises);\n for (const res of chunkResults) {\n if (res.status === 'updated') publishedCount++;\n else if (res.status === 'skipped') skippedCount++;\n results.push(res);\n }\n jobState.processedCount = results.length;\n jobState.updatedCount = publishedCount;\n jobState.skippedCount = skippedCount;\n jobState.failedCount = results.filter((r) => r.status === 'error').length;\n }\n\n const affectedUids = new Set(targets.map((t) => t.uid));\n affectedUids.forEach((uid) => {\n invalidateCollectionCache(uid);\n });\n\n const failedCount = results.filter((r) => r.status === 'error').length;\n jobState.failedCount = failedCount;\n jobState.completedAt = new Date().toISOString();\n jobState.isLive = publishedCount > 0;\n jobState.status =\n failedCount === 0 && publishedCount > 0\n ? 'successful'\n : failedCount > 0 && publishedCount > 0\n ? 'partial_failure'\n : failedCount > 0\n ? 'failed'\n : 'successful';\n jobState.results = results.map((r) => ({\n ...r,\n isLive: r.status === 'updated',\n }));\n\n const batchSummary = {\n batchId,\n attribute: '(publish)',\n value: 'published',\n updatedCount: publishedCount,\n skippedCount,\n totalTargets: targetsMap.size,\n publishOnApproval: true,\n unreviewedConsent,\n };\n\n // Stateless audit recording\n await strapi.plugin('bulk-updater').service('audit').recordBatch(\n batchSummary,\n results,\n currentUser\n );\n\n return {\n success: true,\n batchId,\n publishedCount,\n updatedCount: publishedCount,\n skippedCount,\n failedCount,\n totalTargets: targetsMap.size,\n isLive: publishedCount > 0,\n status: jobState.status,\n results,\n };\n}\n\nasync function executeBatchByPayload(\n strapi: Core.Strapi,\n batch: PendingBatch,\n currentUser: any\n) {\n if (batch.payload?.action === 'csv_import') {\n const csvService = strapi.plugin('bulk-updater').service('csv');\n return await csvService.executeCsvPendingBatch(\n batch.payload.uid,\n batch.payload.rows,\n batch.id,\n batch.payload.options,\n currentUser\n );\n } else if (batch.payload?.action === 'publish') {\n return await executePublishBatchInternal(strapi, batch.payload, currentUser, batch.id);\n } else {\n return await executeBatchInternal(strapi, batch.payload, currentUser, batch.id);\n }\n}\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => {\n // Initialize periodic runner for off-peak queue execution\n if (!runnerInterval) {\n runnerInterval = setInterval(async () => {\n if (isRunnerRunning) return;\n isRunnerRunning = true;\n try {\n const config = getExecutionWindowConfig(strapi);\n const { isBusinessHours } = checkBusinessHours(config);\n\n for (const [id, batch] of pendingBatches.entries()) {\n if (batch.status === 'queued_offpeak' && !isBusinessHours) {\n strapi.log.info(`[bulk-updater] Executing off-peak queued batch: ${id}`);\n const result = await executeBatchByPayload(strapi, batch, batch.createdBy);\n batch.status = 'executed';\n batch.executionResult = result;\n }\n }\n } catch (err) {\n strapi.log.error('[bulk-updater] Scheduled runner error:', err);\n } finally {\n isRunnerRunning = false;\n }\n }, 30000);\n }\n\n return {\n /**\n * Lightweight Schema Discovery:\n * Returns schema definitions, valid attributes, and total counts (<15KB payload)\n * Previews up to 10 entries per collection to ensure instantaneous initial paint.\n * Utilizes in-memory schema memoization and database high-watermark signature caching.\n */\n async getModels() {\n const allContentTypes = strapi.contentTypes || {};\n const auditConfig = strapi.plugin('bulk-updater').service('audit').getAuditConfig();\n const auditContentType = auditConfig?.contentType;\n\n // 1. Static schema discovery memoized in-memory\n if (!staticSchemaCache) {\n const allAttributesSet = new Set<string>();\n const systemFields = [\n 'createdAt',\n 'updatedAt',\n 'publishedAt',\n 'createdBy',\n 'updatedBy',\n 'locale',\n 'localizations',\n ];\n\n const configuredCollections = strapi.config.get(\n 'plugin::bulk-updater.collections'\n ) as string[] | string | undefined;\n\n const isWildcard =\n configuredCollections === '*' ||\n configuredCollections === 'all' ||\n (Array.isArray(configuredCollections) &&\n (configuredCollections.includes('*') || configuredCollections.includes('all')));\n\n let targetUids: string[];\n if (\n !isWildcard &&\n configuredCollections &&\n Array.isArray(configuredCollections) &&\n configuredCollections.length > 0\n ) {\n targetUids = configuredCollections.filter((uid) => uid in allContentTypes);\n } else {\n targetUids = Object.keys(allContentTypes).filter(\n (uid) =>\n uid.startsWith('api::') &&\n !uid.includes('bulk-updater') &&\n uid !== auditContentType\n );\n }\n\n const metaByUid: Record<string, any> = {};\n const allRelationsMeta: Record<string, RelationMeta> = {};\n const allAttributesMeta: Record<string, AttributeMeta> = {};\n\n for (const uid of targetUids) {\n const contentType = allContentTypes[uid];\n if (!contentType || (contentType.kind !== 'collectionType' && contentType.kind !== 'singleType')) continue;\n\n const isSingleType = contentType.kind === 'singleType';\n const rawAttrs = contentType.attributes || {};\n const relationsByAttr: Record<string, RelationMeta> = {};\n const colAttributesMeta: Record<string, AttributeMeta> = {};\n const nestedComponentAttrs: string[] = [];\n\n const validAttrs = Object.keys(rawAttrs).filter((attrKey) => {\n if (systemFields.includes(attrKey)) return false;\n\n if (rawAttrs[attrKey].type === 'dynamiczone') {\n const dzDef = rawAttrs[attrKey];\n const dzComponents = Array.isArray(dzDef.components) ? dzDef.components : [];\n for (const compUid of dzComponents) {\n // Generic path across all components (e.g. blocks.title)\n const compAttrs = discoverComponentAttributes(\n strapi,\n compUid,\n attrKey,\n 1,\n 5,\n systemFields,\n allContentTypes,\n relationsByAttr,\n allRelationsMeta,\n colAttributesMeta\n );\n nestedComponentAttrs.push(...compAttrs);\n\n // Component-scoped path (e.g. blocks[shared.heading].title)\n const scopedAttrs = discoverComponentAttributes(\n strapi,\n compUid,\n `${attrKey}[${compUid}]`,\n 1,\n 5,\n systemFields,\n allContentTypes,\n relationsByAttr,\n allRelationsMeta,\n colAttributesMeta\n );\n nestedComponentAttrs.push(...scopedAttrs);\n }\n return false;\n }\n\n if (rawAttrs[attrKey].type === 'component') {\n const compDef = rawAttrs[attrKey];\n if (compDef.component) {\n const compAttrs = discoverComponentAttributes(\n strapi,\n compDef.component,\n attrKey,\n 1,\n 5,\n systemFields,\n allContentTypes,\n relationsByAttr,\n allRelationsMeta,\n colAttributesMeta\n );\n nestedComponentAttrs.push(...compAttrs);\n }\n return false;\n }\n\n if (rawAttrs[attrKey].type === 'relation') {\n const rel = rawAttrs[attrKey];\n const targetUid = rel.target;\n if (!targetUid || !allContentTypes[targetUid]) return false;\n const targetInfo = allContentTypes[targetUid]?.info;\n const isMulti = rel.relation === 'oneToMany' || rel.relation === 'manyToMany';\n const relMeta: RelationMeta = {\n isRelation: true,\n relationType: rel.relation,\n targetUid,\n targetDisplayName: targetInfo?.displayName || targetUid,\n isMulti,\n };\n relationsByAttr[attrKey] = relMeta;\n allRelationsMeta[attrKey] = relMeta;\n colAttributesMeta[attrKey] = { depth: 0, type: 'relation', isRelation: true };\n return true;\n }\n\n colAttributesMeta[attrKey] = { depth: 0, type: rawAttrs[attrKey].type };\n return true;\n });\n\n const allColAttrs = Array.from(new Set([...validAttrs, ...nestedComponentAttrs]));\n allColAttrs.forEach((attr) => {\n allAttributesSet.add(attr);\n if (colAttributesMeta[attr]) {\n allAttributesMeta[attr] = colAttributesMeta[attr];\n }\n });\n\n metaByUid[uid] = {\n uid,\n kind: contentType.kind,\n isSingleType,\n draftAndPublish: Boolean(contentType.options?.draftAndPublish),\n singularName: contentType.info?.singularName || uid,\n pluralName: contentType.info?.pluralName || uid,\n displayName: contentType.info?.displayName || uid,\n attributes: allColAttrs,\n attributesMeta: colAttributesMeta,\n relations: relationsByAttr,\n };\n }\n\n staticSchemaCache = {\n attributes: Array.from(allAttributesSet),\n attributesMeta: allAttributesMeta,\n targetUids: Object.keys(metaByUid),\n metaByUid,\n relationsMeta: allRelationsMeta,\n };\n }\n\n const collections = [];\n const signatures: string[] = [];\n\n // 2. High-watermark check per collection with throttled concurrency (batches of 10)\n // Prevents database connection pool exhaustion and file locks on 100+ collection schemas\n const BATCH_CONCURRENCY = 10;\n const collectionResults: Array<any> = [];\n\n for (let i = 0; i < staticSchemaCache.targetUids.length; i += BATCH_CONCURRENCY) {\n const batchUids = staticSchemaCache.targetUids.slice(i, i + BATCH_CONCURRENCY);\n const batchRes = await Promise.all(\n batchUids.map(async (uid) => {\n const meta = staticSchemaCache!.metaByUid[uid];\n if (!meta) return null;\n\n const signature = await getCollectionSignature(strapi, uid);\n const cached = modelsCache.get(uid);\n if (cached && cached.signature === signature) {\n return {\n collection: {\n ...meta,\n totalEntries: cached.totalCount,\n entries: cached.entries,\n },\n signature: `${uid}=${signature}`,\n };\n }\n\n let entries: any[] = [];\n let totalCount = 0;\n try {\n const populateOption = buildDeepPopulate(allContentTypes[uid]?.attributes || {}, strapi.components);\n\n if (meta.isSingleType) {\n const singleArgs: any = {};\n if (populateOption) {\n singleArgs.populate = populateOption;\n }\n const singleDoc: any = await (strapi.documents(uid as any) as any).findFirst(singleArgs);\n if (singleDoc) {\n entries = [singleDoc];\n totalCount = 1;\n }\n } else {\n totalCount = await strapi.documents(uid as any).count();\n const findArgs: any = {\n limit: 10,\n sort: { createdAt: 'desc' },\n };\n if (populateOption) {\n findArgs.populate = populateOption;\n }\n entries = await strapi.documents(uid as any).findMany(findArgs);\n }\n } catch (err) {\n strapi.log.error(`[bulk-updater] Failed to fetch entries for ${uid}:`, err);\n entries = [];\n totalCount = 0;\n }\n\n const formattedEntries = (entries || []).map(formatEntryRecord);\n\n modelsCache.set(uid, {\n signature,\n totalCount,\n entries: formattedEntries,\n });\n\n return {\n collection: {\n ...meta,\n totalEntries: totalCount,\n entries: formattedEntries,\n },\n signature: `${uid}=${signature}`,\n };\n })\n );\n collectionResults.push(...batchRes);\n }\n\n for (const res of collectionResults) {\n if (res) {\n collections.push(res.collection);\n signatures.push(res.signature);\n }\n }\n\n const executionConfig = getExecutionWindowConfig(strapi);\n const windowStatus = checkBusinessHours(executionConfig);\n const pendingCount = Array.from(pendingBatches.values()).filter(\n (b) => b.status === 'pending_approval' || b.status === 'queued_offpeak'\n ).length;\n\n const etag = `W/\"models-${crypto.createHash('md5').update(`${signatures.join('|')}:${pendingCount}:${windowStatus.isBusinessHours}:${windowStatus.currentServerTime}:${windowStatus.timeZone}`).digest('hex')}\"`;\n\n return {\n success: true,\n attributes: staticSchemaCache.attributes,\n attributesMeta: staticSchemaCache.attributesMeta,\n collections,\n relationsMeta: staticSchemaCache.relationsMeta,\n maxDiscoveredDepth: 5,\n executionWindow: {\n ...executionConfig,\n ...windowStatus,\n },\n pendingBatchesCount: pendingCount,\n auditEnabled: Boolean(auditConfig?.enabled),\n etag,\n };\n },\n\n /**\n * On-Demand Paginated Collection Entries:\n * Supports server-side pagination (limit / start) and database query pushdown for filters.\n * Cached in-process with cross-pod high-watermark signature validation.\n */\n async getCollectionEntries(\n uid: string,\n {\n page = 1,\n pageSize = 10,\n attribute,\n searchAttribute,\n filterOperator,\n filterQuery,\n search,\n sortField,\n sortOrder = 'desc',\n }: {\n page?: number;\n pageSize?: number;\n attribute?: string;\n searchAttribute?: string;\n filterOperator?: string;\n filterQuery?: string;\n search?: string;\n sortField?: string;\n sortOrder?: 'asc' | 'desc';\n }\n ) {\n const contentType = strapi.contentTypes[uid];\n if (!contentType) {\n throw new Error(`Collection with UID \"${uid}\" does not exist.`);\n }\n\n const limit = Math.min(Math.max(Number(pageSize) || 10, 1), 500);\n const currentPage = Math.max(Number(page) || 1, 1);\n const start = (currentPage - 1) * limit;\n\n const isSingleType = contentType.kind === 'singleType';\n const targetFilterAttr = searchAttribute || attribute;\n\n // 1. Signature-based caching verification\n const signature = await getCollectionSignature(strapi, uid);\n const cacheKey = `${uid}:${limit}:${start}:${attribute || ''}:${searchAttribute || ''}:${filterOperator || ''}:${filterQuery || ''}:${search || ''}:${sortField || ''}:${sortOrder}`;\n const cached = queryCache.get(cacheKey);\n\n const etag = `W/\"entry-${crypto.createHash('md5').update(`${cacheKey}:${signature}`).digest('hex')}\"`;\n\n if (cached && cached.signature === signature && Date.now() - cached.timestamp < CACHE_TTL_MS) {\n return {\n ...cached.data,\n cached: true,\n etag,\n };\n }\n\n let result: any;\n\n // Build database filters pushdown\n const filters: Record<string, any> = {};\n\n const attrs = contentType.attributes || {};\n let colHasAttribute = false;\n let isNestedAttr = false;\n let isRootDz = false;\n let parts: string[] = [];\n\n let resolvedFilterAttr = targetFilterAttr;\n if (targetFilterAttr) {\n const resolvedField = resolveContentTypeField(contentType, targetFilterAttr);\n if (resolvedField) {\n resolvedFilterAttr = resolvedField;\n colHasAttribute = true;\n } else {\n const parsed = parseDynamicZonePath(targetFilterAttr);\n if (parsed.rootKey && contentType.attributes?.[parsed.rootKey]?.type === 'dynamiczone') {\n isRootDz = true;\n colHasAttribute = true;\n isNestedAttr = true;\n parts = parsed.cleanPath.split('.');\n } else if (targetFilterAttr.includes('.') || targetFilterAttr.includes('[')) {\n isNestedAttr = isDeepComponentField(contentType, strapi.components, targetFilterAttr);\n if (isNestedAttr) {\n colHasAttribute = true;\n parts = parsed.cleanPath.split('.');\n }\n }\n }\n }\n\n const normOp = (filterOperator || '').toLowerCase().replace(/_/g, '');\n\n // If a specific attribute filter is active, check if the collection actually has the attribute\n if (normOp && normOp !== 'none') {\n if (!colHasAttribute) {\n // Collection does not possess this attribute: return 0 matching entries\n result = {\n uid,\n displayName: contentType.info?.displayName || uid,\n isSingleType,\n draftAndPublish: Boolean(contentType.options?.draftAndPublish),\n entries: [],\n pagination: {\n page: 1,\n pageSize: limit,\n total: 0,\n pageCount: 0,\n },\n };\n queryCache.set(cacheKey, { signature, data: result, timestamp: Date.now() });\n return { ...result, cached: false, etag };\n }\n\n let condition: any = undefined;\n const q = (filterQuery || '').trim();\n\n const targetAttrSchema = isNestedAttr\n ? getLeafAttributeSchema(contentType, strapi.components, targetFilterAttr)\n : attrs[resolvedFilterAttr];\n const isRelation = targetAttrSchema?.type === 'relation';\n const isStringLike = ['string', 'text', 'email', 'richtext', 'uid'].includes(targetAttrSchema?.type);\n\n if (isRelation) {\n const targetUid = targetAttrSchema?.target;\n const targetContentType = targetUid ? strapi.contentTypes[targetUid] : undefined;\n const targetAttrs = targetContentType?.attributes || {};\n const targetStringAttrs = Object.keys(targetAttrs).filter((k) =>\n ['string', 'text', 'email', 'uid'].includes(targetAttrs[k]?.type)\n );\n\n if (normOp === 'empty') {\n condition = { documentId: { $null: true } };\n } else if (normOp === 'notempty') {\n condition = { documentId: { $notNull: true } };\n } else if (q !== '') {\n const orConditions: any[] = [];\n targetStringAttrs.slice(0, 5).forEach((k) => {\n if (normOp === 'equals') {\n orConditions.push({ [k]: { $eqi: q } });\n } else if (normOp === 'startswith') {\n orConditions.push({ [k]: { $startsWithi: q } });\n } else if (normOp === 'endswith') {\n orConditions.push({ [k]: { $endsWithi: q } });\n } else if (normOp === 'notequals') {\n orConditions.push({ [k]: { $ne: q } });\n } else if (normOp === 'notcontains') {\n orConditions.push({ [k]: { $notContainsi: q } });\n } else {\n orConditions.push({ [k]: { $containsi: q } });\n }\n });\n orConditions.push({ documentId: { $eq: q } });\n if (/^\\d+$/.test(q)) {\n orConditions.push({ id: { $eq: Number(q) } });\n }\n condition = orConditions.length === 1 ? orConditions[0] : { $or: orConditions };\n }\n } else if (normOp === 'empty') {\n condition = isStringLike ? { $or: [{ $null: true }, { $eq: '' }] } : { $null: true };\n } else if (normOp === 'notempty') {\n condition = isStringLike ? { $and: [{ $notNull: true }, { $ne: '' }] } : { $notNull: true };\n } else if (q !== '') {\n switch (normOp) {\n case 'equals':\n condition = { $containsi: q };\n break;\n case 'notequals':\n condition = { $notContainsi: q };\n break;\n case 'contains':\n condition = { $containsi: q };\n break;\n case 'notcontains':\n condition = { $notContainsi: q };\n break;\n case 'startswith':\n condition = { $startsWith: q };\n break;\n case 'endswith':\n condition = { $endsWith: q };\n break;\n }\n }\n\n if (condition !== undefined) {\n if (isNestedAttr) {\n if (isRootDz) {\n // Dynamic zones cannot be filtered via database pushdown in Strapi 5 (causes \"Invalid key <zone>\").\n // Evaluated in-memory across all components after fetching entries.\n } else {\n const deepFilter = buildDeepFilter(parts, condition);\n Object.assign(filters, deepFilter);\n }\n } else {\n if (normOp === 'empty' && isStringLike) {\n filters.$or = [\n { [resolvedFilterAttr]: { $null: true } },\n { [resolvedFilterAttr]: { $eq: '' } },\n ];\n } else if (normOp === 'notempty' && isStringLike) {\n filters[resolvedFilterAttr] = { $notNull: true, $ne: '' };\n } else {\n filters[resolvedFilterAttr] = condition;\n }\n }\n }\n }\n\n if (search && search.trim() !== '') {\n const q = search.trim();\n const searchableAttrs = Object.keys(attrs).filter((k) =>\n ['string', 'text', 'email', 'uid'].includes(attrs[k]?.type)\n );\n\n if (searchableAttrs.length > 0) {\n const orList = searchableAttrs.slice(0, 6).map((k) => ({\n [k]: { $containsi: q },\n }));\n\n if (Object.keys(filters).length > 0) {\n const existingFilters = { ...filters };\n Object.keys(filters).forEach((k) => delete filters[k]);\n filters.$and = [existingFilters, { $or: orList }];\n } else {\n filters.$or = orList;\n }\n }\n }\n\n const populateOption = buildDeepPopulate(contentType.attributes, strapi.components);\n\n if (isSingleType) {\n let singleDoc: any = null;\n try {\n const singleArgs: any = {\n filters: Object.keys(filters).length > 0 ? filters : undefined,\n };\n if (populateOption) {\n singleArgs.populate = populateOption;\n }\n singleDoc = await (strapi.documents(uid as any) as any).findFirst(singleArgs);\n } catch {\n singleDoc = null;\n }\n result = {\n uid,\n displayName: contentType.info?.displayName || uid,\n isSingleType: true,\n draftAndPublish: Boolean(contentType.options?.draftAndPublish),\n entries: singleDoc ? [formatEntryRecord(singleDoc)] : [],\n pagination: {\n page: 1,\n pageSize: 1,\n total: singleDoc ? 1 : 0,\n pageCount: singleDoc ? 1 : 0,\n },\n };\n } else {\n let sortClause: any = {};\n if (sortField && sortField.includes('.')) {\n const sortParts = sortField.split('.');\n if (isDeepComponentField(contentType, strapi.components, sortField)) {\n sortClause = buildDeepFilter(sortParts, sortOrder);\n } else {\n sortClause['createdAt'] = 'desc';\n }\n } else if (sortField) {\n const resolvedField = resolveContentTypeField(contentType, sortField);\n if (resolvedField) {\n sortClause[resolvedField] = sortOrder;\n } else {\n sortClause['createdAt'] = 'desc';\n }\n } else {\n sortClause['createdAt'] = 'desc';\n }\n\n if (isRootDz && normOp && normOp !== 'none') {\n // Dynamic zone filter active: fetch candidates safely and filter in-memory across all components\n const findManyArgs: any = {\n limit: 500,\n filters: Object.keys(filters).length > 0 ? filters : undefined,\n sort: sortClause,\n };\n if (populateOption) {\n findManyArgs.populate = populateOption;\n }\n\n const rawEntries = await strapi.documents(uid as any).findMany(findManyArgs);\n const qVal = (filterQuery || '').trim().toLowerCase();\n\n const passesDzFilter = (entry: any) => {\n const matches = getAllNestedValues(entry, targetFilterAttr);\n if (normOp === 'empty') {\n return matches.length === 0 || matches.every((m) => {\n const v = m.value;\n if (v === undefined || v === null) return true;\n if (Array.isArray(v)) return v.length === 0;\n if (typeof v === 'object') return Object.keys(v).length === 0;\n return String(v).trim() === '';\n });\n }\n if (normOp === 'notempty') {\n return matches.some((m) => {\n const v = m.value;\n if (v === undefined || v === null) return false;\n if (Array.isArray(v)) return v.length > 0;\n if (typeof v === 'object') return Object.keys(v).length > 0;\n return String(v).trim() !== '';\n });\n }\n\n const testSingleValue = (v: any): boolean => {\n if (v === undefined || v === null) return false;\n if (Array.isArray(v)) return v.some(testSingleValue);\n if (typeof v === 'object') {\n return (\n testSingleValue(v.name) ||\n testSingleValue(v.title) ||\n testSingleValue(v.email) ||\n testSingleValue(v.username) ||\n testSingleValue(v.documentId) ||\n testSingleValue(v.id) ||\n testSingleValue(v.slug)\n );\n }\n const valStr = String(v).toLowerCase();\n switch (normOp) {\n case 'equals': return valStr === qVal;\n case 'notequals': return valStr !== qVal;\n case 'contains': return valStr.includes(qVal);\n case 'notcontains': return !valStr.includes(qVal);\n case 'startswith': return valStr.startsWith(qVal);\n case 'endswith': return valStr.endsWith(qVal);\n default: return true;\n }\n };\n\n return matches.some((m) => testSingleValue(m.value));\n };\n\n const matchedEntries = (rawEntries || []).filter(passesDzFilter);\n const totalEntries = matchedEntries.length;\n const paginatedEntries = matchedEntries.slice(start, start + limit);\n\n result = {\n uid,\n displayName: contentType.info?.displayName || uid,\n isSingleType: false,\n draftAndPublish: Boolean(contentType.options?.draftAndPublish),\n entries: paginatedEntries.map(formatEntryRecord),\n pagination: {\n page: currentPage,\n pageSize: limit,\n total: totalEntries,\n pageCount: Math.ceil(totalEntries / limit) || 1,\n },\n };\n } else {\n const findManyArgs: any = {\n start,\n limit,\n filters: Object.keys(filters).length > 0 ? filters : undefined,\n sort: sortClause,\n };\n if (populateOption) {\n findManyArgs.populate = populateOption;\n }\n\n const [entries, totalEntries] = await Promise.all([\n strapi.documents(uid as any).findMany(findManyArgs),\n strapi.documents(uid as any).count({\n filters: Object.keys(filters).length > 0 ? filters : undefined,\n }),\n ]);\n\n result = {\n uid,\n displayName: contentType.info?.displayName || uid,\n isSingleType: false,\n draftAndPublish: Boolean(contentType.options?.draftAndPublish),\n entries: (entries || []).map(formatEntryRecord),\n pagination: {\n page: currentPage,\n pageSize: limit,\n total: totalEntries,\n pageCount: Math.ceil(totalEntries / limit) || 1,\n },\n };\n }\n }\n\n // Store in queryCache with bounding limit\n if (queryCache.size >= MAX_QUERY_CACHE_SIZE) {\n const toDelete = Array.from(queryCache.keys()).slice(0, 100);\n toDelete.forEach((k) => queryCache.delete(k));\n }\n queryCache.set(cacheKey, { signature, data: result, timestamp: Date.now() });\n\n return {\n ...result,\n cached: false,\n etag,\n };\n },\n\n /**\n * Get available target entities for a relation field:\n * Cached in-process with cross-pod signature validation.\n */\n async getRelationOptions(targetUid: string) {\n if (!targetUid || !strapi.contentTypes[targetUid]) {\n throw new Error(`Target content type \"${targetUid}\" does not exist.`);\n }\n\n const cacheKey = `rel_options:${targetUid}`;\n const signature = await getCollectionSignature(strapi, targetUid);\n const cached = queryCache.get(cacheKey);\n if (cached && cached.signature === signature) {\n return cached.data;\n }\n\n const docs = await strapi.documents(targetUid as any).findMany({\n limit: 100,\n sort: { createdAt: 'desc' },\n });\n\n const options = (docs || []).map((doc: any) => {\n const label = doc.name || doc.title || doc.email || doc.username || `Entry #${doc.id || doc.documentId}`;\n return {\n documentId: doc.documentId,\n label,\n };\n });\n\n const result = { targetUid, options };\n queryCache.set(cacheKey, { signature, data: result, timestamp: Date.now() });\n return result;\n },\n\n /**\n * Preview bulk update changes before execution:\n * Reads current values and computes proposed new values without mutating data.\n */\n async previewBatch({\n attribute,\n value,\n selectedEntries = [],\n selectedCollections = [],\n isRegex = false,\n regexPattern = '',\n }: {\n attribute: string;\n value: string;\n selectedEntries?: Array<{ uid: string; documentId: string; dynamicZoneIndexes?: number[]; targetComponentUid?: string }>;\n selectedCollections?: string[];\n isRegex?: boolean;\n regexPattern?: string;\n }) {\n if (!attribute) {\n throw new Error('Attribute name is required.');\n }\n\n const targetsMap = new Map<string, { uid: string; documentId: string; dynamicZoneIndexes?: number[]; targetComponentUid?: string }>();\n\n // 1. Add entire collections if selected\n for (const colUid of selectedCollections) {\n if (!strapi.contentTypes[colUid]) continue;\n const entries = await strapi.documents(colUid as any).findMany();\n for (const entry of (entries || []) as any[]) {\n const key = `${colUid}@@@${entry.documentId}`;\n targetsMap.set(key, { uid: colUid, documentId: entry.documentId });\n }\n }\n\n // 2. Add individually selected entries\n for (const item of selectedEntries) {\n if (!item.uid || !item.documentId) continue;\n const key = `${item.uid}@@@${item.documentId}`;\n targetsMap.set(key, {\n uid: item.uid,\n documentId: item.documentId,\n dynamicZoneIndexes: item.dynamicZoneIndexes,\n targetComponentUid: item.targetComponentUid,\n });\n }\n\n if (targetsMap.size === 0) {\n throw new Error('No collections or entries were selected for preview.');\n }\n\n let regexObj: RegExp | null = null;\n if (isRegex && regexPattern) {\n try {\n regexObj = new RegExp(regexPattern, 'g');\n } catch (e: any) {\n throw new Error(`Invalid regular expression: ${e.message}`);\n }\n }\n\n const targets = Array.from(targetsMap.values());\n const diffs: any[] = [];\n let willUpdateCount = 0;\n let unchangedCount = 0;\n let skippedCount = 0;\n\n for (const target of targets) {\n const contentType = strapi.contentTypes[target.uid];\n const displayName = contentType?.info?.displayName || target.uid;\n\n try {\n const isNested = attribute.includes('.');\n const isComponentNested = isNested && isDeepComponentField(contentType, strapi.components, attribute);\n\n const attrDef = contentType?.attributes?.[attribute];\n const hasAttribute = Boolean(attrDef) || isComponentNested;\n\n if (!hasAttribute) {\n skippedCount++;\n diffs.push({\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: `Entry #${target.documentId}`,\n attribute,\n oldValue: null,\n newValue: null,\n oldDisplay: '—',\n newDisplay: '—',\n hasChange: false,\n status: 'will_skip',\n message: `Attribute \"${attribute}\" does not exist in schema for ${displayName}`,\n });\n continue;\n }\n\n let currentEntry: any;\n if (isComponentNested) {\n const findOneArgs: any = { documentId: target.documentId };\n const populateOption = buildDeepPopulate(contentType.attributes, strapi.components);\n if (populateOption) {\n findOneArgs.populate = populateOption;\n }\n currentEntry = await strapi.documents(target.uid as any).findOne(findOneArgs);\n } else if (attrDef?.type === 'relation') {\n currentEntry = await strapi.documents(target.uid as any).findOne({\n documentId: target.documentId,\n populate: [attribute],\n });\n } else {\n currentEntry = await strapi.documents(target.uid as any).findOne({\n documentId: target.documentId,\n });\n }\n\n const entryLabel =\n currentEntry?.name ||\n currentEntry?.title ||\n currentEntry?.email ||\n `Entry #${target.documentId}`;\n\n if (isComponentNested) {\n const parsed = parseDynamicZonePath(attribute);\n const rootKey = parsed.rootKey;\n const isRootDz = contentType?.attributes?.[rootKey]?.type === 'dynamiczone';\n const targetIndexes = target.dynamicZoneIndexes;\n const targetComponentUid = target.targetComponentUid || parsed.targetComponentUid;\n\n if (isRootDz && currentEntry?.[rootKey] && Array.isArray(currentEntry[rootKey])) {\n let affectedMatches = getAllNestedValues({ [rootKey]: currentEntry[rootKey] }, attribute);\n if (targetIndexes && targetIndexes.length > 0) {\n affectedMatches = affectedMatches.filter((m) => targetIndexes.includes(m.index));\n }\n if (targetComponentUid) {\n affectedMatches = affectedMatches.filter((m) => m.componentUid === targetComponentUid);\n }\n\n if (affectedMatches.length > 0) {\n for (const match of affectedMatches) {\n let blockNewVal = value;\n if (regexObj && typeof match.value === 'string') {\n blockNewVal = match.value.replace(regexObj, value);\n }\n const hasChange = String(match.value ?? '') !== String(blockNewVal ?? '');\n if (hasChange) {\n willUpdateCount++;\n } else {\n unchangedCount++;\n }\n\n diffs.push({\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: `${entryLabel} [Block #${match.index} (${match.componentName})]`,\n attribute: `${rootKey}[#${match.index} ${match.componentName}].${parsed.subPath}`,\n oldValue: match.value ?? null,\n newValue: blockNewVal,\n oldDisplay: match.value !== undefined && match.value !== null && String(match.value).trim() !== '' ? String(match.value) : '(empty)',\n newDisplay: String(blockNewVal ?? ''),\n hasChange,\n status: hasChange ? 'will_update' : 'unchanged',\n message: hasChange ? 'Block value will be updated' : 'Block already has target value',\n });\n }\n continue;\n }\n }\n\n const currentVal = getDeepProperty(currentEntry, attribute);\n\n let newValue = value;\n if (regexObj && typeof currentVal === 'string') {\n newValue = currentVal.replace(regexObj, value);\n }\n\n const hasChange = String(currentVal ?? '') !== String(newValue ?? '');\n if (hasChange) {\n willUpdateCount++;\n } else {\n unchangedCount++;\n }\n\n diffs.push({\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: entryLabel,\n attribute,\n oldValue: currentVal ?? null,\n newValue,\n oldDisplay: currentVal !== undefined && currentVal !== null ? String(currentVal) : '(empty)',\n newDisplay: String(newValue ?? ''),\n hasChange,\n status: hasChange ? 'will_update' : 'unchanged',\n message: hasChange ? 'Value will be updated' : 'Already has target value',\n });\n continue;\n }\n\n if (attrDef?.type === 'relation') {\n const isMulti = attrDef.relation === 'oneToMany' || attrDef.relation === 'manyToMany';\n const currentRel = currentEntry?.[attribute];\n\n let oldDocIds: string[] = [];\n let oldDisplay = '';\n if (isMulti && Array.isArray(currentRel)) {\n oldDocIds = currentRel.map((r: any) => r.documentId).filter(Boolean);\n oldDisplay = currentRel.map((r: any) => r.name || r.title || r.email || r.documentId).join(', ') || '(empty)';\n } else if (currentRel) {\n oldDocIds = currentRel.documentId ? [currentRel.documentId] : [];\n oldDisplay = currentRel.name || currentRel.title || currentRel.email || currentRel.documentId || '(empty)';\n } else {\n oldDisplay = '(unlinked / none)';\n }\n\n let mode: 'set' | 'connect' | 'disconnect' | 'clear' = 'set';\n let targetDocIds: string[] = [];\n let newDisplay = '';\n\n if (value === '__clear__' || value === '') {\n mode = 'clear';\n newDisplay = '(cleared / unlinked)';\n } else {\n try {\n const parsed = JSON.parse(value);\n if (parsed && typeof parsed === 'object' && parsed.mode) {\n mode = parsed.mode;\n targetDocIds = Array.isArray(parsed.documentIds) ? parsed.documentIds : (parsed.documentId ? [parsed.documentId] : []);\n newDisplay = parsed.label || targetDocIds.join(', ') || `[${mode}]`;\n } else if (Array.isArray(parsed)) {\n targetDocIds = parsed;\n newDisplay = targetDocIds.join(', ');\n } else {\n targetDocIds = [value];\n newDisplay = value;\n }\n } catch {\n targetDocIds = [value];\n newDisplay = value;\n }\n }\n\n const hasChange = oldDisplay !== newDisplay;\n if (hasChange) {\n willUpdateCount++;\n } else {\n unchangedCount++;\n }\n\n diffs.push({\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: entryLabel,\n attribute,\n oldValue: { isRelation: true, documentIds: oldDocIds, display: oldDisplay },\n newValue: { isRelation: true, mode, documentIds: targetDocIds, display: newDisplay },\n oldDisplay,\n newDisplay,\n hasChange,\n status: hasChange ? 'will_update' : 'unchanged',\n message: hasChange ? `Relation will be modified (${mode})` : 'Relation already set to this target',\n });\n continue;\n }\n\n // Scalar attributes\n let newValue = value;\n const currentVal = currentEntry?.[attribute];\n\n if (regexObj && typeof currentVal === 'string') {\n newValue = currentVal.replace(regexObj, value);\n }\n\n const hasChange = String(currentVal ?? '') !== String(newValue ?? '');\n if (hasChange) {\n willUpdateCount++;\n } else {\n unchangedCount++;\n }\n\n diffs.push({\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: entryLabel,\n attribute,\n oldValue: currentVal ?? null,\n newValue,\n oldDisplay: currentVal !== undefined && currentVal !== null ? String(currentVal) : '(empty)',\n newDisplay: String(newValue ?? ''),\n hasChange,\n status: hasChange ? 'will_update' : 'unchanged',\n message: hasChange ? 'Value will be updated' : 'Already matches target value',\n });\n } catch (err: any) {\n skippedCount++;\n diffs.push({\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: `Entry #${target.documentId}`,\n attribute,\n oldValue: null,\n newValue: null,\n oldDisplay: '—',\n newDisplay: '—',\n hasChange: false,\n status: 'will_skip',\n message: `Error inspecting entry: ${err.message}`,\n });\n }\n }\n\n return {\n success: true,\n summary: {\n total: targets.length,\n willUpdate: willUpdateCount,\n unchanged: unchangedCount,\n skipped: skippedCount,\n },\n diffs,\n };\n },\n\n /**\n * Batch Update API with Maker-Checker and Off-Peak Scheduling:\n */\n async batchUpdate(\n {\n attribute,\n value,\n selectedEntries = [],\n selectedCollections = [],\n isRegex = false,\n regexPattern = '',\n executionMode = 'immediate',\n makerNotes = '',\n forceImmediate = false,\n publishOnApproval = true,\n publishStrategy = 'safe',\n unreviewedConsent = false,\n unreviewedCount = 0,\n }: {\n attribute: string;\n value: string;\n selectedEntries?: Array<{ uid: string; documentId: string; dynamicZoneIndexes?: number[]; targetComponentUid?: string }>;\n selectedCollections?: string[];\n isRegex?: boolean;\n regexPattern?: string;\n executionMode?: 'immediate' | 'queue_offpeak' | 'maker_checker';\n makerNotes?: string;\n forceImmediate?: boolean;\n publishOnApproval?: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n unreviewedCount?: number;\n },\n currentUser?: any\n ) {\n if (!attribute) {\n throw new Error('Attribute name is required.');\n }\n\n const executionConfig = getExecutionWindowConfig(strapi);\n const { isBusinessHours, policyMessage } = checkBusinessHours(executionConfig);\n\n // 1. Enterprise Maker-Checker Flow:\n if (executionMode === 'maker_checker') {\n const summary = await computeTargetsSummary(strapi, { selectedCollections, selectedEntries });\n if (summary.totalTargets === 0) {\n throw new Error('No collections or entries were selected for update.');\n }\n\n const batchId = `batch_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const batch: PendingBatch = {\n id: batchId,\n createdAt: new Date().toISOString(),\n createdBy: currentUser\n ? {\n id: currentUser.id,\n email: currentUser.email,\n firstname: currentUser.firstname,\n lastname: currentUser.lastname,\n username: currentUser.username,\n }\n : { email: 'admin@system.local' },\n payload: { attribute, value, selectedEntries, selectedCollections, isRegex, regexPattern, publishOnApproval, publishStrategy, unreviewedConsent, unreviewedCount },\n summary: {\n attribute,\n value,\n totalTargets: summary.totalTargets,\n collectionBreakdown: summary.collectionBreakdown,\n publishOnApproval,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n },\n status: 'pending_approval',\n executionMode: 'maker_checker',\n makerNotes,\n };\n\n pendingBatches.set(batchId, batch);\n batchJobsMap.set(batchId, {\n id: batchId,\n createdAt: batch.createdAt,\n createdBy: batch.createdBy,\n status: 'pending_approval',\n executionMode: 'maker_checker',\n attribute,\n value,\n totalTargets: summary.totalTargets,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: Boolean(publishOnApproval),\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n makerNotes,\n results: [],\n });\n\n return {\n success: true,\n pending: true,\n batchId,\n status: 'pending_approval',\n message: 'Batch submitted for Checker authorization (4-Eyes Maker-Checker Workflow).',\n batch,\n };\n }\n\n // 2. Off-Peak Queued Batch:\n if (executionMode === 'queue_offpeak') {\n const summary = await computeTargetsSummary(strapi, { selectedCollections, selectedEntries });\n if (summary.totalTargets === 0) {\n throw new Error('No collections or entries were selected for update.');\n }\n\n const batchId = `batch_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const batch: PendingBatch = {\n id: batchId,\n createdAt: new Date().toISOString(),\n createdBy: currentUser\n ? {\n id: currentUser.id,\n email: currentUser.email,\n firstname: currentUser.firstname,\n lastname: currentUser.lastname,\n username: currentUser.username,\n }\n : { email: 'admin@system.local' },\n payload: { attribute, value, selectedEntries, selectedCollections, isRegex, regexPattern, publishOnApproval, publishStrategy, unreviewedConsent, unreviewedCount },\n summary: {\n attribute,\n value,\n totalTargets: summary.totalTargets,\n collectionBreakdown: summary.collectionBreakdown,\n publishOnApproval,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n },\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n makerNotes,\n };\n\n pendingBatches.set(batchId, batch);\n batchJobsMap.set(batchId, {\n id: batchId,\n createdAt: batch.createdAt,\n createdBy: batch.createdBy,\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n attribute,\n value,\n totalTargets: summary.totalTargets,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: Boolean(publishOnApproval),\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n makerNotes,\n results: [],\n });\n\n return {\n success: true,\n pending: true,\n batchId,\n status: 'queued_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n message: `Batch queued for server off-peak maintenance window (${executionConfig.offPeakStartTime}).`,\n batch,\n };\n }\n\n // 3. Immediate execution request with Server Business Hours enforcement:\n if (executionConfig.enabled && executionConfig.autoQueueDuringBusinessHours && isBusinessHours && !forceImmediate) {\n const summary = await computeTargetsSummary(strapi, { selectedCollections, selectedEntries });\n if (summary.totalTargets === 0) {\n throw new Error('No collections or entries were selected for update.');\n }\n\n const batchId = `batch_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const batch: PendingBatch = {\n id: batchId,\n createdAt: new Date().toISOString(),\n createdBy: currentUser\n ? {\n id: currentUser.id,\n email: currentUser.email,\n firstname: currentUser.firstname,\n lastname: currentUser.lastname,\n username: currentUser.username,\n }\n : { email: 'admin@system.local' },\n payload: { attribute, value, selectedEntries, selectedCollections, isRegex, regexPattern, publishOnApproval, publishStrategy, unreviewedConsent, unreviewedCount },\n summary: {\n attribute,\n value,\n totalTargets: summary.totalTargets,\n collectionBreakdown: summary.collectionBreakdown,\n publishOnApproval,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n },\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n makerNotes: 'Automatically queued due to peak business hours restriction.',\n };\n\n pendingBatches.set(batchId, batch);\n batchJobsMap.set(batchId, {\n id: batchId,\n createdAt: batch.createdAt,\n createdBy: batch.createdBy,\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n attribute,\n value,\n totalTargets: summary.totalTargets,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: Boolean(publishOnApproval),\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n policyMessage,\n makerNotes: 'Automatically queued due to peak business hours restriction.',\n results: [],\n });\n\n return {\n success: true,\n pending: true,\n batchId,\n status: 'queued_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n message: policyMessage,\n batch,\n };\n }\n\n // 4. Immediate execution\n return await executeBatchInternal(\n strapi,\n { attribute, value, selectedEntries, selectedCollections, isRegex, regexPattern, publishOnApproval, publishStrategy, unreviewedConsent },\n currentUser\n );\n },\n\n /**\n * Bulk Publish selected entries or collections\n */\n async batchPublish(\n {\n selectedEntries = [],\n selectedCollections = [],\n executionMode = 'immediate',\n makerNotes = '',\n forceImmediate = false,\n unreviewedConsent = false,\n unreviewedCount = 0,\n }: {\n selectedEntries?: Array<{ uid: string; documentId: string }>;\n selectedCollections?: string[];\n executionMode?: 'immediate' | 'queue_offpeak' | 'maker_checker';\n makerNotes?: string;\n forceImmediate?: boolean;\n unreviewedConsent?: boolean;\n unreviewedCount?: number;\n },\n currentUser?: any\n ) {\n const executionConfig = getExecutionWindowConfig(strapi);\n const { isBusinessHours, policyMessage } = checkBusinessHours(executionConfig);\n\n // 1. Enterprise Maker-Checker Flow:\n if (executionMode === 'maker_checker') {\n const summary = await computeTargetsSummary(strapi, { selectedCollections, selectedEntries });\n if (summary.totalTargets === 0) {\n throw new Error('No collections or entries were selected to publish.');\n }\n\n const batchId = `batch_pub_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const batch: PendingBatch = {\n id: batchId,\n createdAt: new Date().toISOString(),\n createdBy: currentUser\n ? {\n id: currentUser.id,\n email: currentUser.email,\n firstname: currentUser.firstname,\n lastname: currentUser.lastname,\n username: currentUser.username,\n }\n : { email: 'admin@system.local' },\n payload: { action: 'publish', attribute: '(publish)', value: 'published', selectedEntries, selectedCollections, publishOnApproval: true, unreviewedConsent, unreviewedCount },\n summary: {\n attribute: '(publish)',\n value: 'published',\n totalTargets: summary.totalTargets,\n collectionBreakdown: summary.collectionBreakdown,\n publishOnApproval: true,\n unreviewedConsent,\n unreviewedCount,\n },\n status: 'pending_approval',\n executionMode: 'maker_checker',\n makerNotes,\n };\n\n pendingBatches.set(batchId, batch);\n batchJobsMap.set(batchId, {\n id: batchId,\n createdAt: batch.createdAt,\n createdBy: batch.createdBy,\n status: 'pending_approval',\n executionMode: 'maker_checker',\n attribute: '(publish)',\n value: 'published',\n totalTargets: summary.totalTargets,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: true,\n unreviewedConsent,\n unreviewedCount,\n makerNotes,\n results: [],\n });\n\n return {\n success: true,\n pending: true,\n batchId,\n status: 'pending_approval',\n message: 'Bulk publish batch submitted for Checker authorization (4-Eyes Maker-Checker Workflow).',\n batch,\n };\n }\n\n // 2. Off-Peak Queued Batch:\n if (executionMode === 'queue_offpeak') {\n const summary = await computeTargetsSummary(strapi, { selectedCollections, selectedEntries });\n if (summary.totalTargets === 0) {\n throw new Error('No collections or entries were selected to publish.');\n }\n\n const batchId = `batch_pub_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const batch: PendingBatch = {\n id: batchId,\n createdAt: new Date().toISOString(),\n createdBy: currentUser\n ? {\n id: currentUser.id,\n email: currentUser.email,\n firstname: currentUser.firstname,\n lastname: currentUser.lastname,\n username: currentUser.username,\n }\n : { email: 'admin@system.local' },\n payload: { action: 'publish', attribute: '(publish)', value: 'published', selectedEntries, selectedCollections, publishOnApproval: true, unreviewedConsent, unreviewedCount },\n summary: {\n attribute: '(publish)',\n value: 'published',\n totalTargets: summary.totalTargets,\n collectionBreakdown: summary.collectionBreakdown,\n publishOnApproval: true,\n unreviewedConsent,\n unreviewedCount,\n },\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n makerNotes,\n };\n\n pendingBatches.set(batchId, batch);\n batchJobsMap.set(batchId, {\n id: batchId,\n createdAt: batch.createdAt,\n createdBy: batch.createdBy,\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n attribute: '(publish)',\n value: 'published',\n totalTargets: summary.totalTargets,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: true,\n unreviewedConsent,\n unreviewedCount,\n makerNotes,\n results: [],\n });\n\n return {\n success: true,\n pending: true,\n batchId,\n status: 'queued_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n message: `Bulk publish batch queued for server off-peak maintenance window (${executionConfig.offPeakStartTime}).`,\n batch,\n };\n }\n\n // 3. Peak hours auto-queue check\n if (executionConfig.enabled && executionConfig.autoQueueDuringBusinessHours && isBusinessHours && !forceImmediate) {\n const summary = await computeTargetsSummary(strapi, { selectedCollections, selectedEntries });\n if (summary.totalTargets === 0) {\n throw new Error('No collections or entries were selected to publish.');\n }\n\n const batchId = `batch_pub_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const batch: PendingBatch = {\n id: batchId,\n createdAt: new Date().toISOString(),\n createdBy: currentUser\n ? {\n id: currentUser.id,\n email: currentUser.email,\n firstname: currentUser.firstname,\n lastname: currentUser.lastname,\n username: currentUser.username,\n }\n : { email: 'admin@system.local' },\n payload: { action: 'publish', attribute: '(publish)', value: 'published', selectedEntries, selectedCollections, publishOnApproval: true, unreviewedConsent, unreviewedCount },\n summary: {\n attribute: '(publish)',\n value: 'published',\n totalTargets: summary.totalTargets,\n collectionBreakdown: summary.collectionBreakdown,\n publishOnApproval: true,\n unreviewedConsent,\n unreviewedCount,\n },\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n makerNotes: 'Automatically queued due to peak business hours restriction.',\n };\n\n pendingBatches.set(batchId, batch);\n batchJobsMap.set(batchId, {\n id: batchId,\n createdAt: batch.createdAt,\n createdBy: batch.createdBy,\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n attribute: '(publish)',\n value: 'published',\n totalTargets: summary.totalTargets,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: true,\n unreviewedConsent,\n unreviewedCount,\n policyMessage,\n makerNotes: 'Automatically queued due to peak business hours restriction.',\n results: [],\n });\n\n return {\n success: true,\n pending: true,\n batchId,\n status: 'queued_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n message: policyMessage,\n batch,\n };\n }\n\n // 4. Immediate execution\n return await executePublishBatchInternal(\n strapi,\n { selectedEntries, selectedCollections, unreviewedConsent },\n currentUser\n );\n },\n\n /**\n * Get Pending & Queued Batches\n */\n getPendingBatches() {\n const executionConfig = getExecutionWindowConfig(strapi);\n const windowStatus = checkBusinessHours(executionConfig);\n const batches = Array.from(pendingBatches.values()).sort(\n (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()\n );\n\n return {\n success: true,\n batches,\n executionWindow: {\n ...executionConfig,\n ...windowStatus,\n },\n };\n },\n\n /**\n * Checker Approves Batch\n */\n async approveBatch(batchId: string, checkerUser: any, options: { executeImmediately?: boolean } = { executeImmediately: true }) {\n const batch = pendingBatches.get(batchId);\n if (!batch) {\n throw new Error(`Pending batch ${batchId} not found.`);\n }\n if (batch.status !== 'pending_approval') {\n throw new Error(`Batch ${batchId} is not pending approval (current status: ${batch.status}).`);\n }\n\n batch.approval = {\n checkerUser: checkerUser\n ? {\n id: checkerUser.id,\n email: checkerUser.email,\n firstname: checkerUser.firstname,\n lastname: checkerUser.lastname,\n username: checkerUser.username,\n }\n : { email: 'checker@system.local' },\n decisionDate: new Date().toISOString(),\n };\n\n const config = getExecutionWindowConfig(strapi);\n const { isBusinessHours } = checkBusinessHours(config);\n\n if (options.executeImmediately || !isBusinessHours) {\n batch.status = 'approved';\n const result = await executeBatchByPayload(strapi, batch, checkerUser);\n batch.status = 'executed';\n batch.executionResult = result;\n return {\n success: true,\n batchId,\n status: 'executed',\n message: 'Batch approved and executed successfully by Checker.',\n batch,\n result,\n };\n } else {\n batch.status = 'approved';\n return {\n success: true,\n batchId,\n status: 'approved',\n message: `Batch approved by Checker. Queued for execution during off-peak window (${config.offPeakStartTime}).`,\n batch,\n };\n }\n },\n\n /**\n * Checker Rejects Batch\n */\n rejectBatch(batchId: string, checkerUser: any, reason: string = 'Rejected by Checker') {\n const batch = pendingBatches.get(batchId);\n if (!batch) {\n throw new Error(`Pending batch ${batchId} not found.`);\n }\n batch.status = 'rejected';\n batch.approval = {\n checkerUser: checkerUser\n ? {\n id: checkerUser.id,\n email: checkerUser.email,\n firstname: checkerUser.firstname,\n lastname: checkerUser.lastname,\n username: checkerUser.username,\n }\n : { email: 'checker@system.local' },\n decisionDate: new Date().toISOString(),\n rejectionReason: reason,\n };\n\n return {\n success: true,\n batchId,\n status: 'rejected',\n message: `Batch rejected by Checker: ${reason}`,\n batch,\n };\n },\n\n /**\n * Run Batch Immediately\n */\n async executeNow(batchId: string, currentUser: any) {\n const batch = pendingBatches.get(batchId);\n if (!batch) {\n throw new Error(`Pending batch ${batchId} not found.`);\n }\n if (batch.status === 'executed') {\n throw new Error(`Batch ${batchId} has already been executed.`);\n }\n\n const result = await executeBatchByPayload(strapi, batch, currentUser);\n batch.status = 'executed';\n batch.executionResult = result;\n\n return {\n success: true,\n batchId,\n status: 'executed',\n message: 'Batch executed immediately.',\n batch,\n result,\n };\n },\n\n /**\n * Get real-time or historical processing status of a batch job\n */\n async getBatchStatus(batchId: string) {\n if (!batchId) throw new Error('batchId is required');\n\n let job = batchJobsMap.get(batchId);\n if (job) {\n return { success: true, batch: job };\n }\n\n const pending = pendingBatches.get(batchId);\n if (pending) {\n const pendingJob: BatchJobState = {\n id: pending.id,\n createdAt: pending.createdAt,\n createdBy: pending.createdBy,\n status: pending.status as any,\n executionMode: pending.executionMode,\n scheduledFor: pending.scheduledFor,\n attribute: pending.payload.attribute,\n value: pending.payload.value,\n totalTargets: pending.summary.totalTargets,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: Boolean(pending.payload.publishOnApproval),\n policyMessage: pending.makerNotes,\n results: [],\n };\n return { success: true, batch: pendingJob };\n }\n\n // Fallback: Query historical audit log\n try {\n const auditService = strapi.plugin('bulk-updater').service('audit');\n const historyData = await auditService.getHistory();\n const records = Array.isArray(historyData?.history) ? historyData.history : [];\n const found = records.find((r: any) => r.batchId === batchId);\n\n if (found) {\n const total = found.totalTargets || (found.updatedCount + found.skippedCount) || 1;\n const historicalJob: BatchJobState = {\n id: found.batchId,\n createdAt: found.executedAt || found.createdAt || new Date().toISOString(),\n startedAt: found.executedAt || found.createdAt,\n completedAt: found.executedAt || found.createdAt,\n createdBy: {\n email: found.userEmail || 'admin@strapi.io',\n firstname: found.userName || 'Admin',\n },\n status: found.isRolledBack ? 'failed' : 'successful',\n executionMode: 'immediate',\n attribute: found.attribute,\n value: found.value,\n totalTargets: total,\n processedCount: total,\n updatedCount: found.updatedCount || 0,\n skippedCount: found.skippedCount || 0,\n failedCount: 0,\n isLive: !found.isRolledBack && found.updatedCount > 0,\n publishOnApproval: true,\n results: (found.diffs || []).map((d: any) => ({\n uid: d.uid,\n collectionName: d.collectionName || d.uid,\n documentId: d.documentId,\n label: d.label || `Entry #${d.documentId}`,\n attribute: d.attribute || found.attribute,\n oldValue: d.oldValue,\n newValue: d.newValue,\n status: d.status || 'updated',\n isLive: !found.isRolledBack,\n message: d.message || 'Updated via bulk update',\n })),\n };\n batchJobsMap.set(batchId, historicalJob);\n return { success: true, batch: historicalJob };\n }\n } catch (err) {\n // Fallthrough\n }\n\n throw new Error(`Batch with ID \"${batchId}\" was not found.`);\n },\n\n /**\n * Downloadable execution report (CSV or JSON)\n */\n async getBatchReport(batchId: string, format: string = 'csv') {\n const statusRes = await this.getBatchStatus(batchId);\n const batch = statusRes.batch;\n\n function escapeCsvVal(val: any): string {\n if (val === null || val === undefined) return '';\n let str = typeof val === 'object' ? JSON.stringify(val) : String(val);\n str = str.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\n if (/^[=+@-]$/.test(str.charAt(0))) {\n str = `'${str}`;\n }\n if (str.includes(',') || str.includes('\"') || str.includes('\\n')) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n return str;\n }\n\n const headers = [\n 'Batch ID',\n 'Collection UID',\n 'Collection Name',\n 'Document ID',\n 'Record Title / Identifier',\n 'Attribute Name',\n 'Previous Value',\n 'New Live Value',\n 'Processing Status',\n 'Live On Server',\n 'Details / Message',\n 'Executed At',\n 'Operator',\n ];\n\n const rows: string[] = [headers.join(',')];\n\n for (const item of batch.results || []) {\n const row = [\n escapeCsvVal(batch.id),\n escapeCsvVal(item.uid),\n escapeCsvVal(item.collectionName),\n escapeCsvVal(item.documentId),\n escapeCsvVal(item.label),\n escapeCsvVal(item.attribute),\n escapeCsvVal(item.oldValue),\n escapeCsvVal(item.newValue),\n escapeCsvVal(item.status === 'updated' ? 'Updated' : item.status === 'error' ? 'Failed' : 'Skipped'),\n escapeCsvVal(item.isLive ? 'YES (Live on Site)' : 'NO'),\n escapeCsvVal(item.message),\n escapeCsvVal(batch.completedAt || batch.createdAt),\n escapeCsvVal(batch.createdBy?.email || 'admin@strapi.io'),\n ];\n rows.push(row.join(','));\n }\n\n const safeBatchId = batch.id.replace(/[^a-zA-Z0-9_-]/g, '_');\n const filename = `bulk_update_report_${safeBatchId}_${new Date().toISOString().slice(0, 10)}.csv`;\n\n return {\n success: true,\n filename,\n csvContent: '\\uFEFF' + rows.join('\\r\\n') + '\\r\\n',\n summary: {\n batchId: batch.id,\n status: batch.status,\n isLive: batch.isLive,\n totalTargets: batch.totalTargets,\n updatedCount: batch.updatedCount,\n skippedCount: batch.skippedCount,\n failedCount: batch.failedCount,\n executedAt: batch.completedAt || batch.createdAt,\n operator: batch.createdBy?.email || 'admin@strapi.io',\n },\n batch,\n };\n },\n\n /**\n * Get recent batch jobs for the processing dashboard\n */\n async getRecentBatches() {\n const mergedMap = new Map<string, any>();\n\n // 1. From in-memory batchJobsMap\n for (const [id, job] of batchJobsMap.entries()) {\n mergedMap.set(id, {\n id: job.id,\n createdAt: job.createdAt,\n completedAt: job.completedAt,\n status: job.status,\n isLive: job.isLive,\n executionMode: job.executionMode,\n attribute: job.attribute,\n value: job.value,\n totalTargets: job.totalTargets,\n updatedCount: job.updatedCount,\n skippedCount: job.skippedCount,\n failedCount: job.failedCount,\n operator: job.createdBy?.email || 'admin@strapi.io',\n });\n }\n\n // 2. From pendingBatches\n for (const [id, p] of pendingBatches.entries()) {\n if (!mergedMap.has(id)) {\n mergedMap.set(id, {\n id: p.id,\n createdAt: p.createdAt,\n status: p.status,\n isLive: false,\n executionMode: p.executionMode,\n attribute: p.payload.attribute,\n value: p.payload.value,\n totalTargets: p.summary.totalTargets,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n operator: p.createdBy?.email || 'admin@strapi.io',\n });\n }\n }\n\n // 3. From audit history\n try {\n const auditService = strapi.plugin('bulk-updater').service('audit');\n const historyData = await auditService.getHistory();\n const records = Array.isArray(historyData?.history) ? historyData.history : [];\n for (const r of records) {\n if (!mergedMap.has(r.batchId)) {\n mergedMap.set(r.batchId, {\n id: r.batchId,\n createdAt: r.executedAt || r.createdAt,\n completedAt: r.executedAt,\n status: r.isRolledBack ? 'failed' : 'successful',\n isLive: !r.isRolledBack && r.updatedCount > 0,\n executionMode: 'immediate',\n attribute: r.attribute,\n value: r.value,\n totalTargets: r.totalTargets || (r.updatedCount + r.skippedCount) || 1,\n updatedCount: r.updatedCount || 0,\n skippedCount: r.skippedCount || 0,\n failedCount: 0,\n operator: r.userEmail || 'admin@strapi.io',\n });\n }\n }\n } catch {\n // Ignore\n }\n\n const batches = Array.from(mergedMap.values()).sort(\n (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()\n );\n\n return {\n success: true,\n batches: batches.slice(0, 50),\n };\n },\n\n invalidateCache(uid?: string) {\n if (uid) {\n invalidateCollectionCache(uid);\n } else {\n queryCache.clear();\n modelsCache.clear();\n staticSchemaCache = null;\n }\n },\n\n invalidateCollectionCache(uid: string) {\n invalidateCollectionCache(uid);\n },\n\n registerPendingBatch(batch: PendingBatch, jobState?: BatchJobState) {\n pendingBatches.set(batch.id, batch);\n if (jobState) {\n batchJobsMap.set(batch.id, jobState);\n }\n return batch;\n },\n\n getExecutionWindowConfig() {\n return getExecutionWindowConfig(strapi);\n },\n\n checkBusinessHours(config?: ExecutionWindowConfig) {\n const cfg = config || getExecutionWindowConfig(strapi);\n return checkBusinessHours(cfg);\n },\n };\n};\n","import type { Core } from '@strapi/strapi';\nimport { recordContentHistoryVersion } from './content-history';\n\nexport interface AuditConfig {\n enabled: boolean;\n mode?: 'custom' | 'default' | 'enterprise_native' | 'store' | 'disabled';\n contentType?: string;\n fields?: Record<string, string>;\n isEnterpriseNativeAvailable?: boolean;\n error?: string;\n}\n\nconst DEFAULT_FIELDS: Record<string, string> = {\n batchId: 'batchId',\n attribute: 'attribute',\n value: 'value',\n userEmail: 'userEmail',\n userName: 'userName',\n updatedCount: 'updatedCount',\n skippedCount: 'skippedCount',\n totalTargets: 'totalTargets',\n diffs: 'diffs',\n isRolledBack: 'isRolledBack',\n rolledBackAt: 'rolledBackAt',\n rolledBackBy: 'rolledBackBy',\n executedAt: 'executedAt',\n};\n\nconst DEFAULT_CANDIDATE_TYPES = [\n 'plugin::bulk-updater.audit-log',\n 'api::audit-log.audit-log',\n 'api::audit.audit',\n 'api::bulk-audit-log.bulk-audit-log',\n];\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => ({\n /**\n * Detects whether Strapi Enterprise Native Audit Log service is available.\n */\n getEnterpriseAuditService() {\n try {\n const svc =\n (strapi as any).service?.('admin::audit-logs') ||\n (strapi as any).admin?.services?.['audit-logs'];\n return svc || null;\n } catch {\n return null;\n }\n },\n\n /**\n * Resolves the audit configuration:\n * 1. Explicit consumer custom schema (full declarative control)\n * 2. Zero-config convention auto-detection (api::audit-log.audit-log)\n * 3. Strapi Enterprise native audit log bridge\n * 4. Zero-config plugin core store (works out of the box in 100% of Strapi installations)\n */\n getAuditConfig(): AuditConfig {\n const rawConfig = strapi.config.get('plugin::bulk-updater.audit') as any;\n const eeService = this.getEnterpriseAuditService();\n const isEnterpriseNativeAvailable = Boolean(\n eeService && typeof eeService.save === 'function'\n );\n\n // If consumer explicitly disabled audit\n if (rawConfig && rawConfig.enabled === false) {\n return {\n enabled: false,\n mode: 'disabled',\n isEnterpriseNativeAvailable,\n };\n }\n\n // Tier 1: Explicit consumer custom schema\n if (rawConfig?.contentType) {\n const { contentType, fields } = rawConfig;\n const schema = strapi.contentTypes[contentType];\n if (!schema) {\n return {\n enabled: false,\n mode: 'disabled',\n isEnterpriseNativeAvailable,\n error: `Declared audit contentType \"${contentType}\" does not exist in Strapi schema registry.`,\n };\n }\n\n // Check fields or fallback to DEFAULT_FIELDS\n const resolvedFields = { ...DEFAULT_FIELDS, ...(fields || {}) };\n return {\n enabled: true,\n mode: 'custom',\n contentType,\n fields: resolvedFields,\n isEnterpriseNativeAvailable,\n };\n }\n\n // Tier 2: Zero-config auto-discovery of default audit collection\n for (const candidate of DEFAULT_CANDIDATE_TYPES) {\n if (strapi.contentTypes[candidate]) {\n return {\n enabled: true,\n mode: 'default',\n contentType: candidate,\n fields: DEFAULT_FIELDS,\n isEnterpriseNativeAvailable,\n };\n }\n }\n\n // Tier 3: Strapi Enterprise native audit logs\n if (isEnterpriseNativeAvailable) {\n return {\n enabled: true,\n mode: 'enterprise_native',\n isEnterpriseNativeAvailable: true,\n };\n }\n\n // Tier 4: Zero-config core store fallback (always available in all Strapi installations)\n return {\n enabled: true,\n mode: 'store',\n isEnterpriseNativeAvailable: false,\n };\n },\n\n /**\n * Checks whether audit logging is enabled.\n */\n isAuditEnabled(): boolean {\n const config = this.getAuditConfig();\n return Boolean(config && config.enabled);\n },\n\n /**\n * Convenience alias to log an operation into the audit trail.\n */\n async logOperation(data: {\n batchId: string;\n attribute: string;\n value: string;\n userEmail?: string;\n userName?: string;\n updatedCount: number;\n skippedCount: number;\n totalTargets: number;\n diffs?: any[];\n }) {\n return this.recordBatch(\n {\n batchId: data.batchId,\n attribute: data.attribute,\n value: data.value,\n updatedCount: data.updatedCount,\n skippedCount: data.skippedCount,\n totalTargets: data.totalTargets,\n },\n data.diffs || [],\n {\n email: data.userEmail,\n firstname: data.userName,\n }\n );\n },\n\n /**\n * Optionally writes an audit event directly to Strapi Enterprise's native Audit Logs table.\n */\n async recordToEnterpriseNative(\n action: string,\n payload: Record<string, any>,\n user?: any\n ) {\n try {\n const eeService = this.getEnterpriseAuditService();\n if (eeService && typeof eeService.save === 'function') {\n await eeService.save({\n action,\n date: new Date(),\n userId: user?.id,\n payload,\n });\n strapi.log.info(\n `[bulk-updater] Successfully dispatched event to Strapi Enterprise Audit Log: ${action}`\n );\n }\n } catch (err: any) {\n strapi.log.warn(\n `[bulk-updater] Note: Could not dispatch to Strapi Enterprise native audit log: ${err.message}`\n );\n }\n },\n\n /**\n * Records a batch execution:\n * - Dispatches to Strapi Enterprise native audit log if available\n * - Records to consumer or auto-detected collection type for one-click rollback\n */\n async recordBatch(\n batchSummary: {\n batchId: string;\n attribute: string;\n value: string;\n updatedCount: number;\n skippedCount: number;\n totalTargets: number;\n publishOnApproval?: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n },\n results: any[],\n user?: any\n ) {\n const config = this.getAuditConfig();\n\n // 1. Always attempt Strapi Enterprise native logging if available\n await this.recordToEnterpriseNative(\n 'bulk-updater.batch-update',\n {\n batchId: batchSummary.batchId,\n attribute: batchSummary.attribute,\n value: batchSummary.value,\n updatedCount: batchSummary.updatedCount,\n skippedCount: batchSummary.skippedCount,\n totalTargets: batchSummary.totalTargets,\n publishStrategy: batchSummary.publishStrategy,\n unreviewedConsent: batchSummary.unreviewedConsent,\n },\n user\n );\n\n // 2. Persist to rollback-capable storage\n if (!config.enabled) {\n return null;\n }\n\n if (config.mode === 'store') {\n try {\n const store = strapi.store({ type: 'plugin', name: 'bulk-updater', key: 'audit-history' });\n const stored = (await store.get({})) || { history: [] };\n const history = Array.isArray(stored.history) ? stored.history : [];\n\n const newRecord = {\n id: batchSummary.batchId,\n documentId: batchSummary.batchId,\n batchId: batchSummary.batchId,\n attribute: batchSummary.attribute,\n value: batchSummary.value,\n userEmail: user?.email || 'admin@strapi.io',\n userName: user?.firstname\n ? `${user.firstname} ${user.lastname || ''}`.trim()\n : user?.email || 'Admin',\n updatedCount: batchSummary.updatedCount,\n skippedCount: batchSummary.skippedCount,\n totalTargets: batchSummary.totalTargets,\n publishOnApproval: batchSummary.publishOnApproval,\n publishStrategy: batchSummary.publishStrategy,\n unreviewedConsent: batchSummary.unreviewedConsent,\n diffs: results,\n isRolledBack: false,\n rolledBackAt: null,\n rolledBackBy: null,\n executedAt: new Date().toISOString(),\n };\n\n const updatedHistory = [newRecord, ...history].slice(0, 200);\n await store.set({ value: { history: updatedHistory } });\n return newRecord;\n } catch (err: any) {\n strapi.log.error(`[bulk-updater] Failed to record audit log in core store: ${err.message}`);\n return null;\n }\n }\n\n if (!config.contentType || !config.fields) {\n return null;\n }\n\n const f = config.fields;\n const mappedData: any = {};\n\n if (f.batchId) mappedData[f.batchId] = batchSummary.batchId;\n if (f.attribute) mappedData[f.attribute] = batchSummary.attribute;\n if (f.value) mappedData[f.value] = batchSummary.value;\n if (f.userEmail) mappedData[f.userEmail] = user?.email || 'admin@strapi.io';\n if (f.userName) {\n mappedData[f.userName] = user?.firstname\n ? `${user.firstname} ${user.lastname || ''}`.trim()\n : user?.email || 'Admin';\n }\n if (f.updatedCount) mappedData[f.updatedCount] = batchSummary.updatedCount;\n if (f.skippedCount) mappedData[f.skippedCount] = batchSummary.skippedCount;\n if (f.totalTargets) mappedData[f.totalTargets] = batchSummary.totalTargets;\n if (f.diffs) mappedData[f.diffs] = results;\n if (f.isRolledBack) mappedData[f.isRolledBack] = false;\n if (f.executedAt) mappedData[f.executedAt] = new Date().toISOString();\n\n try {\n const created = await strapi.documents(config.contentType as any).create({\n data: mappedData,\n });\n return created;\n } catch (err: any) {\n strapi.log.error(`[bulk-updater] Failed to record audit log: ${err.message}`);\n return null;\n }\n },\n\n /**\n * Fetches audit history for the UI\n */\n async getHistory() {\n const config = this.getAuditConfig();\n\n if (config.mode === 'enterprise_native' && !config.contentType) {\n return {\n enabled: true,\n mode: 'enterprise_native',\n message:\n 'Strapi Enterprise Native Audit Logs active. Batch events are recorded directly to Strapi Settings > Audit Logs. (To enable one-click document rollback, declare or add an audit-log collection).',\n history: [],\n };\n }\n\n if (config.mode === 'store') {\n try {\n const store = strapi.store({ type: 'plugin', name: 'bulk-updater', key: 'audit-history' });\n const stored = (await store.get({})) || { history: [] };\n const history = Array.isArray(stored.history) ? stored.history : [];\n\n return {\n enabled: true,\n mode: 'store',\n isEnterpriseNativeAvailable: config.isEnterpriseNativeAvailable,\n history,\n };\n } catch (err: any) {\n return {\n enabled: false,\n message: `Failed to read audit history from core store: ${err.message}`,\n history: [],\n };\n }\n }\n\n if (!config.enabled || !config.contentType || !config.fields) {\n return {\n enabled: false,\n message:\n config.error ||\n 'Audit trail is disabled. To enable audit logs & rollback, declare an audit schema in config/plugins.ts or create api::audit-log.audit-log.',\n history: [],\n };\n }\n\n try {\n const records: any[] = await strapi.documents(config.contentType as any).findMany({\n sort: { createdAt: 'desc' } as any,\n });\n\n const f = config.fields;\n const normalized = (records || []).map((r: any) => ({\n id: r.id,\n documentId: r.documentId,\n batchId: r[f.batchId] || r.documentId,\n attribute: r[f.attribute],\n value: r[f.value],\n userEmail: r[f.userEmail] || 'admin@strapi.io',\n userName: r[f.userName] || 'Admin',\n updatedCount: r[f.updatedCount] || 0,\n skippedCount: r[f.skippedCount] || 0,\n totalTargets: r[f.totalTargets] || 0,\n diffs: typeof r[f.diffs] === 'string' ? JSON.parse(r[f.diffs]) : r[f.diffs] || [],\n isRolledBack: Boolean(r[f.isRolledBack]),\n rolledBackAt: r[f.rolledBackAt] || null,\n rolledBackBy: r[f.rolledBackBy] || null,\n executedAt: r[f.executedAt] || r.createdAt,\n }));\n\n return {\n enabled: true,\n mode: config.mode,\n contentType: config.contentType,\n isEnterpriseNativeAvailable: config.isEnterpriseNativeAvailable,\n history: normalized,\n };\n } catch (err: any) {\n return {\n enabled: false,\n message: `Failed to read audit history: ${err.message}`,\n history: [],\n };\n }\n },\n\n /**\n * Helper to revert diff items back to original values\n */\n async revertDiffItems(diffs: any[], userId?: any) {\n let revertedCount = 0;\n const rollbackDetails = [];\n\n for (const item of diffs) {\n if (item.status === 'updated' && item.uid && item.documentId && item.attribute) {\n try {\n const isRel = item.oldValue && typeof item.oldValue === 'object' && item.oldValue.isRelation;\n let rollbackPayload: any;\n\n if (isRel) {\n const oldDocIds = Array.isArray(item.oldValue.documentIds) ? item.oldValue.documentIds : [];\n rollbackPayload = { set: oldDocIds };\n } else {\n rollbackPayload = item.oldValue;\n }\n\n if (item.attribute.includes('.')) {\n const [parentKey, childKey] = item.attribute.split('.');\n const ct = strapi.contentTypes[item.uid];\n if (ct?.attributes?.[parentKey]?.type === 'component') {\n const currentDoc: any = await strapi.documents(item.uid as any).findOne({\n documentId: item.documentId,\n populate: [parentKey],\n });\n const currentParent = currentDoc?.[parentKey] || {};\n const restoredParent = {\n ...currentParent,\n [childKey]: rollbackPayload,\n };\n await strapi.documents(item.uid as any).update({\n documentId: item.documentId,\n data: {\n [parentKey]: restoredParent,\n },\n });\n } else {\n await strapi.documents(item.uid as any).update({\n documentId: item.documentId,\n data: {\n [item.attribute]: rollbackPayload,\n },\n });\n }\n } else {\n await strapi.documents(item.uid as any).update({\n documentId: item.documentId,\n data: {\n [item.attribute]: rollbackPayload,\n },\n });\n }\n\n const ct = strapi.contentTypes[item.uid];\n if (ct?.options?.draftAndPublish) {\n try {\n await (strapi.documents(item.uid as any) as any).publish({\n documentId: item.documentId,\n });\n } catch {}\n }\n\n // Record Content History Version for Strapi Content Manager\n try {\n await recordContentHistoryVersion(strapi, {\n uid: item.uid,\n documentId: item.documentId,\n userId,\n statusOverride: ct?.options?.draftAndPublish ? 'published' : undefined,\n });\n } catch {}\n\n try {\n const bulkService = strapi.plugin('bulk-updater').service('bulkUpdater');\n if (bulkService?.invalidateCache) {\n bulkService.invalidateCache(item.uid);\n }\n } catch {}\n\n revertedCount++;\n rollbackDetails.push({\n uid: item.uid,\n documentId: item.documentId,\n label: item.label,\n attribute: item.attribute,\n revertedTo: item.oldValue,\n status: 'reverted',\n });\n } catch (err: any) {\n rollbackDetails.push({\n uid: item.uid,\n documentId: item.documentId,\n label: item.label,\n status: 'error',\n message: err.message,\n });\n }\n }\n }\n\n return { revertedCount, rollbackDetails };\n },\n\n /**\n * Performs deterministic rollback of a batch\n */\n async rollbackBatch(batchId: string, currentUser?: any) {\n const config = this.getAuditConfig();\n if (!config.enabled) {\n throw new Error('Audit trail is not configured or disabled.');\n }\n\n if (config.mode === 'store') {\n const store = strapi.store({ type: 'plugin', name: 'bulk-updater', key: 'audit-history' });\n const stored = (await store.get({})) || { history: [] };\n const history = Array.isArray(stored.history) ? stored.history : [];\n\n const recordIndex = history.findIndex((r: any) => r.batchId === batchId);\n if (recordIndex === -1) {\n throw new Error(`Batch record with ID \"${batchId}\" was not found in audit trail.`);\n }\n\n const record = history[recordIndex];\n if (record.isRolledBack) {\n throw new Error(`Batch \"${batchId}\" has already been rolled back.`);\n }\n\n const diffs = Array.isArray(record.diffs) ? record.diffs : [];\n const { revertedCount, rollbackDetails } = await this.revertDiffItems(diffs, currentUser?.id);\n\n record.isRolledBack = true;\n record.rolledBackAt = new Date().toISOString();\n record.rolledBackBy = currentUser?.email || 'Admin';\n history[recordIndex] = record;\n await store.set({ value: { history } });\n\n try {\n const affectedUids = new Set(rollbackDetails.map((d: any) => d.uid));\n const bulkService = strapi.plugin('bulk-updater').service('bulkUpdater');\n affectedUids.forEach((uid: any) => {\n if (uid && bulkService?.invalidateCache) {\n bulkService.invalidateCache(uid);\n }\n });\n } catch {}\n\n await this.recordToEnterpriseNative(\n 'bulk-updater.rollback',\n {\n batchId,\n revertedCount,\n },\n currentUser\n );\n\n return {\n success: true,\n batchId,\n revertedCount,\n details: rollbackDetails,\n };\n }\n\n if (!config.contentType || !config.fields) {\n throw new Error('Audit trail is not configured or disabled.');\n }\n\n const f = config.fields;\n const records: any[] = await strapi.documents(config.contentType as any).findMany({\n filters: {\n [f.batchId]: { $eq: batchId },\n } as any,\n });\n\n const record = records?.[0];\n if (!record) {\n throw new Error(`Batch record with ID \"${batchId}\" was not found in audit trail.`);\n }\n\n if (record[f.isRolledBack]) {\n throw new Error(`Batch \"${batchId}\" has already been rolled back.`);\n }\n\n const diffs =\n typeof record[f.diffs] === 'string'\n ? JSON.parse(record[f.diffs])\n : record[f.diffs] || [];\n\n const { revertedCount, rollbackDetails } = await this.revertDiffItems(diffs, currentUser?.id);\n\n const updateData: any = {};\n if (f.isRolledBack) updateData[f.isRolledBack] = true;\n if (f.rolledBackAt) updateData[f.rolledBackAt] = new Date().toISOString();\n if (f.rolledBackBy) {\n updateData[f.rolledBackBy] = currentUser?.email || 'Admin';\n }\n\n await strapi.documents(config.contentType as any).update({\n documentId: record.documentId,\n data: updateData,\n });\n\n // Invalidate affected collection caches\n try {\n const affectedUids = new Set(rollbackDetails.map((d: any) => d.uid));\n const bulkService = strapi.plugin('bulk-updater').service('bulkUpdater');\n affectedUids.forEach((uid: any) => {\n if (uid && bulkService?.invalidateCache) {\n bulkService.invalidateCache(uid);\n }\n });\n } catch {}\n\n // Mirror rollback event to Strapi Enterprise native audit log if available\n await this.recordToEnterpriseNative(\n 'bulk-updater.rollback',\n {\n batchId,\n revertedCount,\n },\n currentUser\n );\n\n return {\n success: true,\n batchId,\n revertedCount,\n details: rollbackDetails,\n };\n },\n});\n","import type { Core } from '@strapi/strapi';\n\nexport interface ValidationRule {\n id: string;\n name: string;\n description?: string;\n collectionUid?: string; // specific collection UID (e.g. 'api::article.article') or '*' (all)\n targetField: string; // dot-path or attribute name, e.g. 'headingLevel' or 'st-featured.titleHeadingStyle.titleStyle'\n quotas: Record<string, number>;\n exceededAction: 'disable' | 'hide';\n enabled: boolean;\n scope: 'entry' | 'document';\n includeRichTextHtml?: boolean; // Scans rich text / CKEditor HTML / Markdown / Blocks headings\n richTextFields?: string[]; // Optional specific rich text paths to scan\n createdAt: string;\n updatedAt: string;\n}\n\nconst DEFAULT_RULES: ValidationRule[] = [\n {\n id: 'rule_seo_heading_h1',\n name: 'SEO Single H1 Page Rule',\n description: 'Enforces that only one H1 heading tag can be selected across all dynamic zone heading blocks within an entry, combined with rich text HTML.',\n collectionUid: '*',\n targetField: 'headingLevel',\n quotas: {\n h1: 1,\n h2: 3,\n },\n exceededAction: 'disable',\n enabled: true,\n scope: 'entry',\n includeRichTextHtml: true,\n richTextFields: [],\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n },\n];\n\n/**\n * Extracts heading counts (h1..h6) from rich text content (HTML strings, Markdown strings, or Strapi Blocks AST)\n */\nexport function extractHeadingsFromRichText(content: any): Record<string, number> {\n const counts: Record<string, number> = { h1: 0, h2: 0, h3: 0, h4: 0, h5: 0, h6: 0 };\n if (!content) return counts;\n\n // 1. Strapi 5 Blocks AST (Array of block nodes)\n if (Array.isArray(content)) {\n for (const node of content) {\n if (node && typeof node === 'object') {\n if (node.type === 'heading' && typeof node.level === 'number') {\n const tag = `h${node.level}`;\n if (counts[tag] !== undefined) counts[tag]++;\n }\n if (Array.isArray(node.children)) {\n const sub = extractHeadingsFromRichText(node.children);\n for (const k of Object.keys(counts)) counts[k] += sub[k];\n }\n }\n }\n return counts;\n }\n\n // 2. String (HTML or Markdown)\n if (typeof content === 'string') {\n for (let level = 1; level <= 6; level++) {\n const tag = `h${level}`;\n // HTML regex: <h1 ...> or <h1> (case-insensitive)\n const htmlMatches = content.match(new RegExp(`<${tag}\\\\b[^>]*>`, 'gi'));\n if (htmlMatches) {\n counts[tag] += htmlMatches.length;\n }\n // Markdown regex: '# Heading' at beginning of line\n const mdRegex = new RegExp(`(?:^|\\\\n)${'#'.repeat(level)}\\\\s+[^\\\\n]+`, 'g');\n const mdMatches = content.match(mdRegex);\n if (mdMatches) {\n counts[tag] += mdMatches.length;\n }\n }\n }\n\n return counts;\n}\n\nexport function cleanKey(str: string): string {\n return (str || '').replace(/[-_]/g, '').toLowerCase().trim();\n}\n\n/**\n * Matches a current property path against a rule targetField.\n * Supports:\n * - Leaf keys (e.g. 'titleStyle')\n * - Component dot paths (e.g. 'titleHeadingStyle.titleStyle')\n * - Dynamic zone paths (e.g. 'content.titleHeadingStyle.titleStyle')\n * - Collection-prefixed paths (e.g. 'st-featured.titleHeadingStyle.titleStyle' or 'api::st-featured.st-featured.titleHeadingStyle.titleStyle')\n * - Wildcards (e.g. 'content.*.titleHeadingStyle.titleStyle')\n * - Sequence matching through intermediate components or dynamic zones\n */\nexport function matchesPath(normalizedPath: string, leafKey: string, targetField: string): boolean {\n if (!targetField) return false;\n const pClean = cleanKey(normalizedPath);\n const kClean = cleanKey(leafKey);\n const tClean = cleanKey(targetField);\n\n // Exact or leaf match\n if (kClean === tClean || pClean === tClean) return true;\n\n // Split into dot-segments\n const targetSegments = targetField\n .replace(/^api::/i, '')\n .split('.')\n .map(cleanKey)\n .filter(Boolean);\n\n const pathSegments = normalizedPath\n .split('.')\n .map(cleanKey)\n .filter(Boolean);\n\n if (targetSegments.length === 0 || pathSegments.length === 0) return false;\n\n // 1. Single-segment targetField: matches leafKey or the final path segment\n if (targetSegments.length === 1) {\n const single = targetSegments[0];\n return kClean === single || pathSegments[pathSegments.length - 1] === single;\n }\n\n // 2. Direct suffix match (e.g. path 'content.titleHeadingStyle.titleStyle' ends with 'titleHeadingStyle.titleStyle')\n let isSuffix = true;\n for (let i = 0; i < targetSegments.length; i++) {\n const tSeg = targetSegments[targetSegments.length - 1 - i];\n const pSeg = pathSegments[pathSegments.length - 1 - i];\n if (tSeg !== '*' && tSeg !== pSeg) {\n isSuffix = false;\n break;\n }\n }\n if (isSuffix) return true;\n\n // 3. Collection prefix stripping: if targetField starts with collection name (e.g. 'st-featured.titleHeadingStyle.titleStyle')\n // Check if targetSegments without the first (or first two) elements matches suffix\n for (let startIdx = 1; startIdx < targetSegments.length; startIdx++) {\n const subTarget = targetSegments.slice(startIdx);\n if (subTarget.length > pathSegments.length) continue;\n let subSuffix = true;\n for (let i = 0; i < subTarget.length; i++) {\n const tSeg = subTarget[subTarget.length - 1 - i];\n const pSeg = pathSegments[pathSegments.length - 1 - i];\n if (tSeg !== '*' && tSeg !== pSeg) {\n subSuffix = false;\n break;\n }\n }\n if (subSuffix) return true;\n }\n\n // 4. In-order sequence match: all target segments appear in relative order along pathSegments\n // e.g. target ['content', 'titleheadingstyle', 'titlestyle'] matches ['content', 'zones', 'herobanner', 'titleheadingstyle', 'titlestyle']\n let pIdx = 0;\n let matchesInOrder = true;\n let tStart = 0;\n // If first target segment looks like collection name and doesn't match first path segment, skip it\n if (targetSegments.length > 2 && targetSegments[0] !== pathSegments[0] && targetSegments[0] !== '*') {\n tStart = 1;\n }\n for (let tIdx = tStart; tIdx < targetSegments.length; tIdx++) {\n const tSeg = targetSegments[tIdx];\n if (tSeg === '*') continue;\n let found = false;\n while (pIdx < pathSegments.length) {\n if (pathSegments[pIdx] === tSeg) {\n found = true;\n pIdx++;\n break;\n }\n pIdx++;\n }\n if (!found) {\n matchesInOrder = false;\n break;\n }\n }\n\n return matchesInOrder;\n}\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => ({\n async getStore() {\n return strapi.store({\n type: 'plugin',\n name: 'bulk-updater',\n key: 'validation-rules',\n });\n },\n\n async getRules(): Promise<ValidationRule[]> {\n const store = await this.getStore();\n const stored = await store.get({});\n if (!stored || !Array.isArray(stored.rules)) {\n // Seed default rules if first time\n await store.set({ value: { rules: DEFAULT_RULES } });\n return DEFAULT_RULES;\n }\n return stored.rules;\n },\n\n async saveRule(ruleData: Partial<ValidationRule>): Promise<ValidationRule> {\n const store = await this.getStore();\n const rules = await this.getRules();\n\n const now = new Date().toISOString();\n let savedRule: ValidationRule;\n\n if (ruleData.id) {\n // Update existing\n const index = rules.findIndex((r) => r.id === ruleData.id);\n if (index !== -1) {\n savedRule = {\n ...rules[index],\n ...ruleData,\n collectionUid: ruleData.collectionUid !== undefined ? ruleData.collectionUid : (rules[index].collectionUid || '*'),\n includeRichTextHtml: ruleData.includeRichTextHtml !== undefined ? Boolean(ruleData.includeRichTextHtml) : Boolean(rules[index].includeRichTextHtml),\n richTextFields: Array.isArray(ruleData.richTextFields) ? ruleData.richTextFields : (rules[index].richTextFields || []),\n updatedAt: now,\n } as ValidationRule;\n rules[index] = savedRule;\n } else {\n savedRule = {\n id: ruleData.id,\n name: ruleData.name || 'New Rule',\n description: ruleData.description || '',\n collectionUid: ruleData.collectionUid || '*',\n targetField: ruleData.targetField || 'headingLevel',\n quotas: ruleData.quotas || { h1: 1 },\n exceededAction: ruleData.exceededAction || 'disable',\n enabled: ruleData.enabled ?? true,\n scope: ruleData.scope || 'entry',\n includeRichTextHtml: Boolean(ruleData.includeRichTextHtml),\n richTextFields: Array.isArray(ruleData.richTextFields) ? ruleData.richTextFields : [],\n createdAt: now,\n updatedAt: now,\n };\n rules.push(savedRule);\n }\n } else {\n // Create new\n const id = `rule_${Date.now()}_${Math.random().toString(36).substring(2, 6)}`;\n savedRule = {\n id,\n name: ruleData.name || 'Custom Quota Rule',\n description: ruleData.description || '',\n collectionUid: ruleData.collectionUid || '*',\n targetField: ruleData.targetField || 'headingLevel',\n quotas: ruleData.quotas || { h1: 1 },\n exceededAction: ruleData.exceededAction || 'disable',\n enabled: ruleData.enabled ?? true,\n scope: ruleData.scope || 'entry',\n includeRichTextHtml: Boolean(ruleData.includeRichTextHtml),\n richTextFields: Array.isArray(ruleData.richTextFields) ? ruleData.richTextFields : [],\n createdAt: now,\n updatedAt: now,\n };\n rules.push(savedRule);\n }\n\n await store.set({ value: { rules } });\n return savedRule;\n },\n\n async deleteRule(ruleId: string): Promise<boolean> {\n const store = await this.getStore();\n const rules = await this.getRules();\n const filtered = rules.filter((r) => r.id !== ruleId);\n await store.set({ value: { rules: filtered } });\n return true;\n },\n\n async toggleRule(ruleId: string, enabled?: boolean): Promise<ValidationRule | null> {\n const store = await this.getStore();\n const rules = await this.getRules();\n const index = rules.findIndex((r) => r.id === ruleId);\n if (index === -1) return null;\n\n const current = rules[index];\n const newEnabled = typeof enabled === 'boolean' ? enabled : !current.enabled;\n const updated = {\n ...current,\n enabled: newEnabled,\n updatedAt: new Date().toISOString(),\n };\n rules[index] = updated;\n await store.set({ value: { rules } });\n return updated;\n },\n\n async scanViolations(ruleId: string): Promise<{\n rule: ValidationRule;\n totalScanned: number;\n totalViolations: number;\n violations: Array<{\n uid: string;\n collectionDisplayName: string;\n documentId: string;\n entryLabel: string;\n violatingOption: string;\n foundCount: number;\n structuredCount: number;\n richTextCount: number;\n maxAllowed: number;\n editUrl: string;\n detail?: string;\n }>;\n }> {\n const rules = await this.getRules();\n const rule = rules.find((r) => r.id === ruleId);\n if (!rule) {\n throw new Error(`Validation rule ${ruleId} not found`);\n }\n\n const targetField = rule.targetField;\n const quotas = rule.quotas || {};\n const violations: Array<any> = [];\n let totalScanned = 0;\n\n const allContentTypes = strapi.contentTypes || {};\n const allComponents = strapi.components || {};\n\n function componentHasField(compUid: string, targetField: string): boolean {\n const comp = allComponents[compUid];\n if (!comp?.attributes) return false;\n if (matchesPath(compUid, compUid, targetField)) return true;\n for (const [attrName, attrDef] of Object.entries(comp.attributes) as any[]) {\n if (matchesPath(attrName, attrName, targetField) || matchesPath(`${compUid}.${attrName}`, attrName, targetField)) return true;\n if (attrDef.type === 'component' && attrDef.component) {\n if (componentHasField(attrDef.component, targetField)) return true;\n } else if (attrDef.type === 'dynamiczone' && Array.isArray(attrDef.components)) {\n if (attrDef.components.some((c: string) => componentHasField(c, targetField))) return true;\n }\n }\n return false;\n }\n\n // Helper: Checks if a content-type schema or any of its components has the target field\n function schemaHasField(ctSchema: any): { hasField: boolean; populateAttrs: Record<string, any> } {\n if (!ctSchema || !ctSchema.attributes) return { hasField: false, populateAttrs: {} };\n const rawAttrs = ctSchema.attributes;\n const populateAttrs: Record<string, any> = {};\n let hasField = false;\n\n for (const [attrKey, attrDef] of Object.entries(rawAttrs) as any[]) {\n if (matchesPath(attrKey, attrKey, targetField)) {\n hasField = true;\n }\n if (attrDef.type === 'component' && attrDef.component) {\n if (componentHasField(attrDef.component, targetField)) {\n hasField = true;\n populateAttrs[attrKey] = { populate: '*' };\n }\n } else if (attrDef.type === 'dynamiczone' && Array.isArray(attrDef.components)) {\n const matchingComp = attrDef.components.some(\n (compUid: string) => componentHasField(compUid, targetField) || matchesPath(`${attrKey}.${compUid}`, compUid, targetField)\n );\n if (matchingComp) {\n hasField = true;\n populateAttrs[attrKey] = { populate: '*' };\n }\n }\n }\n\n return { hasField, populateAttrs };\n }\n\n const candidateUids = Object.keys(allContentTypes).filter((uid) => {\n if (!uid.startsWith('api::') || uid.includes('bulk-updater')) return false;\n if (rule.collectionUid && rule.collectionUid !== '*') {\n if (rule.collectionUid === uid) return true;\n const cleanRuleCol = cleanKey(rule.collectionUid);\n const cleanUid = cleanKey(uid);\n if (cleanUid.includes(cleanRuleCol) || cleanRuleCol.includes(cleanUid)) return true;\n return false;\n }\n return true;\n });\n\n // Filter candidate collections to those that possess targetField in schema, OR if rule has collectionUid specified\n const relevantCollections: Array<{ uid: string; displayName: string; populateOption?: Record<string, any> | string }> = [];\n for (const uid of candidateUids) {\n const ct = allContentTypes[uid];\n if (!ct) continue;\n const { hasField, populateAttrs } = schemaHasField(ct);\n const isTargetCol = rule.collectionUid && (rule.collectionUid === uid || cleanKey(uid).includes(cleanKey(rule.collectionUid)));\n if (hasField || isTargetCol) {\n relevantCollections.push({\n uid,\n displayName: ct.info?.displayName || uid,\n populateOption: Object.keys(populateAttrs).length > 0 ? populateAttrs : '*',\n });\n }\n }\n\n const BATCH_SIZE = 250;\n\n await Promise.all(\n relevantCollections.map(async ({ uid, displayName, populateOption }) => {\n try {\n let page = 1;\n while (true) {\n const entries: any[] = await strapi.documents(uid as any).findMany({\n page,\n pageSize: BATCH_SIZE,\n populate: populateOption,\n });\n\n if (!entries || entries.length === 0) break;\n\n for (const entry of entries) {\n totalScanned++;\n const structuredCounts: Record<string, number> = {};\n const richTextCounts: Record<string, number> = { h1: 0, h2: 0, h3: 0, h4: 0, h5: 0, h6: 0 };\n\n function traverse(obj: any, currentPath = '') {\n if (!obj || typeof obj !== 'object') return;\n const compName = typeof obj.__component === 'string' ? obj.__component : '';\n\n for (const key of Object.keys(obj)) {\n if (key === '__component') continue;\n const val = obj[key];\n const newPath = currentPath ? `${currentPath}.${key}` : key;\n const normalizedPath = newPath.replace(/\\.\\d+/g, '');\n\n const compPath = compName\n ? (currentPath ? `${currentPath}.${compName}.${key}` : `${compName}.${key}`).replace(/\\.\\d+/g, '')\n : '';\n\n const isMatch = matchesPath(normalizedPath, key, targetField) ||\n (compPath ? matchesPath(compPath, key, targetField) : false);\n\n if (isMatch && typeof val === 'string' && val.trim()) {\n const lower = val.toLowerCase().trim();\n structuredCounts[lower] = (structuredCounts[lower] || 0) + 1;\n }\n\n if (rule.includeRichTextHtml) {\n if (typeof val === 'string' && (val.includes('<h') || val.includes('#'))) {\n const headings = extractHeadingsFromRichText(val);\n for (const [tag, count] of Object.entries(headings)) {\n if (count > 0) {\n richTextCounts[tag] = (richTextCounts[tag] || 0) + count;\n }\n }\n } else if (Array.isArray(val) && val.length > 0 && typeof val[0] === 'object' && val[0]?.type) {\n const headings = extractHeadingsFromRichText(val);\n for (const [tag, count] of Object.entries(headings)) {\n if (count > 0) {\n richTextCounts[tag] = (richTextCounts[tag] || 0) + count;\n }\n }\n continue;\n }\n }\n\n if (typeof val === 'object' && val !== null) {\n traverse(val, newPath);\n }\n }\n }\n\n traverse(entry);\n\n for (const [optKey, max] of Object.entries(quotas)) {\n const lowerOpt = optKey.toLowerCase().trim();\n const structCount = structuredCounts[lowerOpt] || 0;\n const rtCount = rule.includeRichTextHtml ? (richTextCounts[lowerOpt] || 0) : 0;\n const combinedCount = structCount + rtCount;\n\n if (combinedCount > max) {\n const entryLabel =\n entry.title || entry.name || entry.email || `Entry #${entry.documentId}`;\n \n let detail = '';\n if (rtCount > 0 && structCount > 0) {\n detail = `${structCount} structured + ${rtCount} in rich text HTML`;\n } else if (rtCount > 0) {\n detail = `${rtCount} in rich text HTML / Markdown`;\n } else {\n detail = `${structCount} in structured component`;\n }\n\n violations.push({\n uid,\n collectionDisplayName: displayName,\n documentId: entry.documentId,\n entryLabel,\n violatingOption: optKey.toUpperCase(),\n foundCount: combinedCount,\n structuredCount: structCount,\n richTextCount: rtCount,\n maxAllowed: max,\n detail,\n editUrl: `/admin/content-manager/collection-types/${uid}/${entry.documentId}`,\n });\n }\n }\n }\n\n if (entries.length < BATCH_SIZE) break;\n page++;\n }\n } catch (err) {\n strapi.log.warn(`[bulk-updater] Failed scanning ${uid} for rule ${ruleId}:`, err);\n }\n })\n );\n\n return {\n rule,\n totalScanned,\n totalViolations: violations.length,\n violations,\n };\n },\n});\n","import type { Core } from '@strapi/strapi';\nimport { recordContentHistoryVersion } from './content-history';\nimport {\n getExecutionWindowConfig,\n checkBusinessHours,\n registerPendingBatch,\n type PendingBatch,\n} from './bulk-updater';\nimport { extractHeadingsFromRichText } from './validation-rules';\n\n/**\n * Robust, Excel-Safe CSV string escaping helper (RFC-4180 compliant)\n */\nfunction escapeCsvValue(val: any): string {\n if (val === null || val === undefined) return '';\n let str = '';\n\n if (val instanceof Date) {\n str = val.toISOString();\n } else if (typeof val === 'object') {\n str = JSON.stringify(val);\n } else {\n str = String(val);\n }\n\n // Normalize CRLF or lone CR inside cells to standard LF\n str = str.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\n\n // Excel CSV Formula Injection Mitigation:\n // If first character is =, +, -, or @, prefix with a single quote to prevent execution in Excel\n if (/^[=+@-]$/.test(str.charAt(0))) {\n str = `'${str}`;\n }\n\n // Quote cell if it contains delimiter, quotes, or newlines\n if (str.includes(',') || str.includes('\"') || str.includes('\\n')) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n return str;\n}\n\n/**\n * RFC-4180 compliant CSV parser that correctly handles:\n * - Multiline strings & HTML content with embedded line breaks (\\n, \\r\\n, \\r) inside quotes\n * - Commas embedded inside double-quoted cells without shifting subsequent columns\n * - Escaped double quotes (\"\" -> \")\n * - Leading/trailing whitespace outside quotes\n * - UTF-8 Byte Order Mark (BOM)\n * - Excel formula injection unescaping ('=, '+, '-, '@)\n */\nexport function parseCsvRows(csvText: string): string[][] {\n if (!csvText) return [];\n\n // Strip UTF-8 BOM if present\n let text = csvText;\n if (text.charCodeAt(0) === 0xfeff) {\n text = text.slice(1);\n }\n\n const rows: string[][] = [];\n let currentRow: string[] = [];\n let currentCell = '';\n let inQuotes = false;\n let cellIsQuoted = false;\n\n for (let i = 0; i < text.length; i++) {\n const char = text[i];\n const nextChar = text[i + 1];\n\n if (inQuotes) {\n if (char === '\"') {\n if (nextChar === '\"') {\n // Escaped quote: \"\" -> \"\n currentCell += '\"';\n i++; // skip second quote\n } else {\n // Closing quote\n inQuotes = false;\n }\n } else {\n // Any character inside quotes (including \\r, \\n, commas, HTML tags) is preserved verbatim\n currentCell += char;\n }\n } else {\n if (char === '\"' && !cellIsQuoted && currentCell.trim() === '') {\n // Opening quote (discards leading whitespace before opening quote)\n inQuotes = true;\n cellIsQuoted = true;\n currentCell = '';\n } else if (char === ',') {\n currentRow.push(cellIsQuoted ? currentCell : currentCell.trim());\n currentCell = '';\n cellIsQuoted = false;\n } else if (char === '\\r') {\n if (nextChar === '\\n') {\n i++; // Skip \\n in \\r\\n sequence\n }\n currentRow.push(cellIsQuoted ? currentCell : currentCell.trim());\n if (currentRow.length > 1 || (currentRow.length === 1 && currentRow[0] !== '')) {\n rows.push(currentRow);\n }\n currentRow = [];\n currentCell = '';\n cellIsQuoted = false;\n } else if (char === '\\n') {\n currentRow.push(cellIsQuoted ? currentCell : currentCell.trim());\n if (currentRow.length > 1 || (currentRow.length === 1 && currentRow[0] !== '')) {\n rows.push(currentRow);\n }\n currentRow = [];\n currentCell = '';\n cellIsQuoted = false;\n } else {\n // If cell was already quoted and closed, ignore trailing whitespace between closing quote and delimiter\n if (!(cellIsQuoted && !inQuotes && (char === ' ' || char === '\\t'))) {\n currentCell += char;\n }\n }\n }\n }\n\n if (currentCell !== '' || cellIsQuoted || currentRow.length > 0) {\n currentRow.push(cellIsQuoted ? currentCell : currentCell.trim());\n if (currentRow.length > 1 || (currentRow.length === 1 && currentRow[0] !== '')) {\n rows.push(currentRow);\n }\n }\n\n return rows;\n}\n\nexport function parseCsv(csvText: string): Array<Record<string, string>> {\n const rows = parseCsvRows(csvText);\n if (rows.length < 2) return [];\n\n const headers = rows[0].map((h) => h.trim());\n const records: Array<Record<string, string>> = [];\n\n for (let i = 1; i < rows.length; i++) {\n const row = rows[i];\n const record: Record<string, string> = {};\n headers.forEach((h, idx) => {\n let val = row[idx] !== undefined ? row[idx] : '';\n if (typeof val === 'string' && /^'[=+@-]/.test(val)) {\n val = val.substring(1);\n }\n record[h] = val;\n });\n records.push(record);\n }\n\n return records;\n}\n\nconst LIFECYCLE_STATUS_WORDS = new Set([\n 'pending review',\n 'pending_review',\n 'pending approval',\n 'pending_approval',\n 'approved',\n 'rejected',\n 'draft',\n 'published',\n 'modified',\n 'supported',\n 'ignored',\n]);\n\nexport function isValidDocId(val: any): boolean {\n if (!val || typeof val !== 'string') return false;\n const trimmed = val.trim();\n if (!trimmed) return false;\n if (LIFECYCLE_STATUS_WORDS.has(trimmed.toLowerCase())) return false;\n if (/\\s/.test(trimmed)) return false;\n return /^[a-zA-Z0-9_-]+$/.test(trimmed);\n}\n\nexport function extractDocId(row: Record<string, any>): string {\n if (!row || typeof row !== 'object') return '';\n const candidates = [\n row.documentId,\n row.document_id,\n row['Document ID'],\n row['Document Id'],\n row['document_id'],\n row.docId,\n row['docId'],\n row.id,\n row.ID,\n row.Id,\n ];\n for (const c of candidates) {\n if (c !== undefined && c !== null) {\n const str = String(c).trim();\n if (isValidDocId(str)) {\n return str;\n }\n }\n }\n return '';\n}\n\nexport function extractLocale(row: Record<string, any>): string | undefined {\n if (!row || typeof row !== 'object') return undefined;\n const candidates = [row.locale, row.Locale, row['locale'], row['Locale']];\n for (const c of candidates) {\n if (c !== undefined && c !== null) {\n const str = String(c).trim();\n if (str && str.toLowerCase() !== 'null' && str.toLowerCase() !== 'undefined') {\n return str;\n }\n }\n }\n return undefined;\n}\n\nexport function extractDetailedErrorMessage(err: any): string {\n if (!err) return 'Error processing row';\n\n // 1. Check err.details?.errors or err.error?.details?.errors (Strapi / Yup standard format)\n const detailsErrors = err.details?.errors || err.error?.details?.errors;\n if (Array.isArray(detailsErrors) && detailsErrors.length > 0) {\n const messages = detailsErrors\n .map((e: any) => {\n if (!e) return '';\n const path = Array.isArray(e.path) ? e.path.join('.') : e.path;\n const msg = e.message || (typeof e === 'string' ? e : JSON.stringify(e));\n return path ? `${path}: ${msg}` : msg;\n })\n .filter(Boolean);\n if (messages.length > 0) return messages.join('; ');\n }\n\n // 2. Check err.inner (Yup's nested ValidationError instances)\n if (Array.isArray(err.inner) && err.inner.length > 0) {\n const messages = err.inner\n .map((e: any) => {\n if (!e) return '';\n const path = e.path;\n const msg = e.message || (typeof e === 'string' ? e : JSON.stringify(e));\n return path ? `${path}: ${msg}` : msg;\n })\n .filter(Boolean);\n if (messages.length > 0) return messages.join('; ');\n }\n\n // 3. Check err.errors (Yup validation error string array)\n if (Array.isArray(err.errors) && err.errors.length > 0) {\n return err.errors.join('; ');\n }\n\n // 4. Check err.details if it is a string or object with message\n if (typeof err.details === 'string' && err.details.trim()) {\n return err.details;\n }\n if (err.details?.message) {\n return err.details.message;\n }\n\n // 5. Check err.message if descriptive\n if (err.message && err.message !== '[object Object]') {\n return err.message;\n }\n\n return 'Error processing row';\n}\n\n/**\n * Field definition discovered for export\n */\ninterface ExportFieldDef {\n key: string;\n label: string;\n type: string;\n}\n\n/**\n * Recursively discovers all exportable fields, fully supporting nested components\n */\nfunction discoverExportFields(\n ct: any,\n allComponents: Record<string, any>,\n maxDepth = 4\n): ExportFieldDef[] {\n const fields: ExportFieldDef[] = [{ key: 'documentId', label: 'documentId', type: 'string' }];\n const excluded = ['createdBy', 'updatedBy', 'localizations'];\n\n function walkComponent(compUid: string, pathPrefix: string, labelPrefix: string, depth: number) {\n if (depth >= maxDepth) return;\n const comp = allComponents[compUid];\n if (!comp?.attributes) return;\n\n for (const [subKey, subDef] of Object.entries(comp.attributes) as any[]) {\n if (excluded.includes(subKey)) continue;\n const keyPath = `${pathPrefix}.${subKey}`;\n const displayLabel = `${labelPrefix} > ${subKey}`;\n\n if (subDef.type === 'component' && subDef.component) {\n if (!subDef.repeatable) {\n walkComponent(subDef.component, keyPath, displayLabel, depth + 1);\n } else {\n fields.push({ key: keyPath, label: displayLabel, type: 'component' });\n }\n } else {\n fields.push({ key: keyPath, label: displayLabel, type: subDef.type });\n }\n }\n }\n\n for (const [attrName, attrDef] of Object.entries(ct.attributes || {}) as any[]) {\n if (excluded.includes(attrName)) continue;\n if (attrDef.type === 'component' && attrDef.component) {\n if (!attrDef.repeatable) {\n walkComponent(attrDef.component, attrName, attrName, 0);\n } else {\n fields.push({ key: attrName, label: attrName, type: 'component' });\n }\n } else {\n fields.push({ key: attrName, label: attrName, type: attrDef.type });\n }\n }\n\n return fields;\n}\n\n/**\n * Builds a deep populate object for Strapi 5 Document Service\n */\nfunction buildDeepPopulate(\n attributes: Record<string, any>,\n allComponents: Record<string, any>,\n depth = 0\n): Record<string, any> | undefined {\n if (depth > 5) return undefined;\n const populate: Record<string, any> = {};\n\n for (const [key, def] of Object.entries(attributes || {}) as any[]) {\n if (def.type === 'component' && def.component) {\n const comp = allComponents[def.component];\n if (comp?.attributes) {\n const subPopulate = buildDeepPopulate(comp.attributes, allComponents, depth + 1);\n if (subPopulate && Object.keys(subPopulate).length > 0) {\n populate[key] = {\n populate: subPopulate,\n };\n } else {\n populate[key] = true;\n }\n } else {\n populate[key] = true;\n }\n } else if (def.type === 'dynamiczone') {\n populate[key] = true;\n } else if (def.type === 'relation' || def.type === 'media') {\n populate[key] = true;\n }\n }\n\n return Object.keys(populate).length > 0 ? populate : undefined;\n}\n\n/**\n * Safely resolves deep nested dot-notation paths (e.g. \"defaultSeo.metaDescription\" or \"author.name\")\n */\nfunction getNestedExportValue(entry: any, path: string): any {\n if (!entry || !path) return '';\n const parts = path.split('.');\n let current: any = entry;\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n if (current === null || current === undefined) return '';\n\n if (Array.isArray(current)) {\n // Repeatable component or array: extract remainder for each element\n const subPath = parts.slice(i).join('.');\n return current\n .map((item) => {\n if (!item) return '';\n if (typeof item === 'object') {\n const val = getNestedExportValue(item, subPath);\n return typeof val === 'object' ? JSON.stringify(val) : String(val ?? '');\n }\n return String(item);\n })\n .filter(Boolean)\n .join('; ');\n }\n\n if (current && typeof current === 'object') {\n if (current[part] !== undefined) {\n current = current[part];\n } else {\n const camel = part.replace(/_([a-z0-9])/g, (_, l) => l.toUpperCase());\n const snake = part.replace(/([A-Z])/g, '_$1').toLowerCase();\n if (current[camel] !== undefined) {\n current = current[camel];\n } else if (current[snake] !== undefined) {\n current = current[snake];\n } else {\n current = undefined;\n }\n }\n } else {\n current = undefined;\n }\n }\n\n if (current === null || current === undefined) return '';\n\n // If Media object\n if (typeof current === 'object' && current.url) {\n return current.url;\n }\n\n // If Relation object\n if (typeof current === 'object' && !Array.isArray(current)) {\n if (current.documentId || current.name || current.title) {\n return current.name || current.title || current.documentId;\n }\n }\n\n // If array of objects (e.g. relations or components)\n if (Array.isArray(current)) {\n return current\n .map((item) => {\n if (!item) return '';\n if (typeof item === 'object') {\n return item.name || item.title || item.documentId || JSON.stringify(item);\n }\n return String(item);\n })\n .filter(Boolean)\n .join('; ');\n }\n\n return current;\n}\n\n\nexport interface ProcessRowsStats {\n total: number;\n created: number;\n updated: number;\n skipped: number;\n newWithoutDocId: number;\n errors: Array<{ row: number; error: string; documentId?: string }>;\n diffs: Array<any>;\n}\n\ninterface CsvImportSession {\n batchId: string;\n uid: string;\n createdAt: number;\n total: number;\n created: number;\n updated: number;\n skipped: number;\n newWithoutDocId: number;\n errors: Array<{ row: number; error: string; documentId?: string }>;\n diffs: Array<any>;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n}\n\nconst csvImportSessions = new Map<string, CsvImportSession>();\n\nfunction cleanupStaleSessions() {\n const oneHourAgo = Date.now() - 3600000;\n for (const [id, session] of csvImportSessions.entries()) {\n if (session.createdAt < oneHourAgo) {\n csvImportSessions.delete(id);\n }\n }\n}\n\nconst SYSTEM_FIELD_KEYS = new Set([\n 'documentid',\n 'document_id',\n 'docid',\n 'id',\n 'createdat',\n 'updatedat',\n 'publishedat',\n 'createdby',\n 'updatedby',\n 'localizations',\n 'locale',\n 'status',\n]);\n\nasync function findExistingDocument(\n strapi: Core.Strapi,\n uid: string,\n targetDocId: string,\n docLocale?: string\n): Promise<any> {\n if (!targetDocId) return null;\n try {\n const queryArgs: any = { documentId: targetDocId };\n if (docLocale) queryArgs.locale = docLocale;\n const found = await (strapi.documents(uid as any) as any).findOne(queryArgs);\n if (found) return found;\n } catch {\n // Strapi 5 throws NotFoundError if documentId does not exist\n }\n\n if (/^\\d+$/.test(targetDocId)) {\n try {\n const queryArgs: any = {\n filters: { id: parseInt(targetDocId, 10) },\n limit: 1,\n };\n if (docLocale) queryArgs.locale = docLocale;\n const list = await (strapi.documents(uid as any) as any).findMany(queryArgs);\n if (list && list.length > 0) return list[0];\n } catch {\n // Ignore\n }\n }\n\n return null;\n}\n\n/**\n * Recursively deep merges two component objects while preserving array values and existing properties.\n */\nfunction deepMergeComponent(existingVal: any, newVal: any): any {\n if (!existingVal || typeof existingVal !== 'object' || Array.isArray(existingVal)) {\n return newVal;\n }\n if (!newVal || typeof newVal !== 'object' || Array.isArray(newVal)) {\n return newVal;\n }\n const merged = { ...existingVal };\n for (const k of Object.keys(newVal)) {\n if (newVal[k] && typeof newVal[k] === 'object' && !Array.isArray(newVal[k])) {\n merged[k] = deepMergeComponent(existingVal[k], newVal[k]);\n } else if (newVal[k] !== undefined) {\n merged[k] = newVal[k];\n }\n }\n return merged;\n}\n\nexport async function processCsvRows(\n strapi: Core.Strapi,\n ct: any,\n uid: string,\n rows: Array<Record<string, string>>,\n startRowNumber: number,\n options: {\n mode?: 'auto' | 'update' | 'create_or_override';\n publish?: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n user?: any;\n }\n): Promise<ProcessRowsStats> {\n const attrs = ct.attributes || {};\n const { mode = 'auto', publish = true, publishStrategy = 'safe', user } = options;\n const isDraftAndPublish = Boolean(ct.options?.draftAndPublish);\n\n const stats: ProcessRowsStats = {\n total: rows.length,\n created: 0,\n updated: 0,\n skipped: 0,\n newWithoutDocId: 0,\n errors: [],\n diffs: [],\n };\n\n for (let i = 0; i < rows.length; i++) {\n const rowNumber = startRowNumber + i;\n const row = rows[i];\n\n let docId = extractDocId(row);\n const rowLocale = extractLocale(row);\n\n // If singleType and no documentId provided in row, auto-detect existing single document\n if (ct.kind === 'singleType' && !docId) {\n try {\n const findSingleArgs: any = {};\n if (rowLocale) findSingleArgs.locale = rowLocale;\n const singleDoc = await (strapi.documents(uid as any) as any).findFirst(findSingleArgs);\n if (singleDoc?.documentId) {\n docId = singleDoc.documentId;\n }\n } catch {}\n }\n\n const payload: Record<string, any> = {};\n\n // Transform and cast row columns to schema field types\n for (const [key, rawVal] of Object.entries(row)) {\n const normalizedKey = key.toLowerCase().replace(/[\\s_-]/g, '');\n if (SYSTEM_FIELD_KEYS.has(normalizedKey)) continue;\n\n if (key.includes('.')) {\n const parts = key.split('.');\n let currentAttrs = attrs;\n let currentTarget = payload;\n let validPath = true;\n\n for (let pIdx = 0; pIdx < parts.length; pIdx++) {\n const part = parts[pIdx];\n const isLeaf = pIdx === parts.length - 1;\n\n if (isLeaf) {\n let leafDef = currentAttrs[part];\n if (!leafDef) {\n const match = Object.keys(currentAttrs).find(\n (k) => k.toLowerCase() === part.toLowerCase() || k.toLowerCase() === part.toLowerCase().replace(/\\s+/g, '')\n );\n if (match) leafDef = currentAttrs[match];\n }\n if (!leafDef) {\n validPath = false;\n break;\n }\n\n // Cast and assign leaf value\n if (rawVal === '' || rawVal === null || rawVal === undefined) {\n // Never set null for repeatable components, relations, or dynamic zones\n if (leafDef.type !== 'dynamiczone' && !(leafDef.type === 'component' && leafDef.repeatable) && leafDef.type !== 'relation') {\n currentTarget[part] = null;\n }\n } else if (leafDef.type === 'integer' || leafDef.type === 'biginteger') {\n const parsedInt = parseInt(rawVal, 10);\n currentTarget[part] = isNaN(parsedInt) ? null : parsedInt;\n } else if (leafDef.type === 'float' || leafDef.type === 'decimal') {\n const parsedFloat = parseFloat(rawVal);\n currentTarget[part] = isNaN(parsedFloat) ? null : parsedFloat;\n } else if (leafDef.type === 'boolean') {\n currentTarget[part] = rawVal.toLowerCase() === 'true' || rawVal === '1';\n } else if (leafDef.type === 'json') {\n try {\n currentTarget[part] = JSON.parse(rawVal);\n } catch {\n currentTarget[part] = rawVal;\n }\n } else if (leafDef.type === 'component' && leafDef.repeatable) {\n try {\n const parsed = JSON.parse(rawVal);\n if (Array.isArray(parsed)) {\n currentTarget[part] = parsed;\n }\n } catch {}\n } else if (leafDef.type === 'relation') {\n try {\n const parsed = JSON.parse(rawVal);\n if (Array.isArray(parsed) || (typeof parsed === 'object' && parsed !== null)) {\n currentTarget[part] = parsed;\n } else if (isValidDocId(rawVal)) {\n currentTarget[part] = rawVal;\n }\n } catch {\n if (isValidDocId(rawVal)) {\n currentTarget[part] = rawVal;\n }\n }\n } else {\n currentTarget[part] = rawVal;\n }\n } else {\n // Intermediate segment\n let compDef = currentAttrs[part];\n if (!compDef) {\n const match = Object.keys(currentAttrs).find(\n (k) => k.toLowerCase() === part.toLowerCase() || k.toLowerCase() === part.toLowerCase().replace(/\\s+/g, '')\n );\n if (match) compDef = currentAttrs[match];\n }\n\n if (compDef?.type === 'component' && !compDef.repeatable && compDef.component) {\n const comp = strapi.components[compDef.component];\n if (!comp?.attributes) {\n validPath = false;\n break;\n }\n if (!currentTarget[part] || typeof currentTarget[part] !== 'object' || Array.isArray(currentTarget[part])) {\n currentTarget[part] = {};\n }\n currentTarget = currentTarget[part];\n currentAttrs = comp.attributes;\n } else {\n validPath = false;\n break;\n }\n }\n }\n continue;\n }\n\n let attrDef = attrs[key];\n if (!attrDef) {\n const matchKey = Object.keys(attrs).find(\n (k) => k.toLowerCase() === key.toLowerCase() || k.toLowerCase() === key.toLowerCase().replace(/\\s+/g, '')\n );\n if (matchKey) {\n attrDef = attrs[matchKey];\n }\n }\n if (!attrDef) continue; // Skip unknown columns\n\n if (rawVal === '' || rawVal === null || rawVal === undefined) {\n // Do not overwrite dynamiczone or repeatable component with null unless explicitly desired\n if (attrDef.type !== 'dynamiczone' && !(attrDef.type === 'component' && attrDef.repeatable)) {\n payload[key] = null;\n }\n continue;\n }\n\n switch (attrDef.type) {\n case 'integer':\n case 'biginteger': {\n const parsedInt = parseInt(rawVal, 10);\n payload[key] = isNaN(parsedInt) ? null : parsedInt;\n break;\n }\n case 'float':\n case 'decimal': {\n const parsedFloat = parseFloat(rawVal);\n payload[key] = isNaN(parsedFloat) ? null : parsedFloat;\n break;\n }\n case 'boolean':\n payload[key] = rawVal.toLowerCase() === 'true' || rawVal === '1';\n break;\n case 'json':\n try {\n payload[key] = JSON.parse(rawVal);\n } catch {\n payload[key] = rawVal;\n }\n break;\n case 'dynamiczone': {\n try {\n const parsed = JSON.parse(rawVal);\n if (\n Array.isArray(parsed) &&\n parsed.every((item) => item && typeof item === 'object' && typeof item.__component === 'string')\n ) {\n payload[key] = parsed;\n }\n } catch {\n // Summary text or unparseable format from export: omit\n }\n break;\n }\n case 'component': {\n if (attrDef.repeatable) {\n try {\n const parsed = JSON.parse(rawVal);\n if (Array.isArray(parsed) && parsed.every((item) => item && typeof item === 'object')) {\n payload[key] = parsed;\n }\n } catch {}\n } else {\n try {\n const parsed = JSON.parse(rawVal);\n if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {\n payload[key] = parsed;\n }\n } catch {}\n }\n break;\n }\n case 'relation': {\n try {\n const parsed = JSON.parse(rawVal);\n if (Array.isArray(parsed) || (typeof parsed === 'object' && parsed !== null)) {\n payload[key] = parsed;\n break;\n }\n } catch {}\n\n if (isValidDocId(rawVal)) {\n payload[key] = rawVal;\n } else if (rawVal.includes(';') || rawVal.includes(',')) {\n const parts = rawVal.split(/[;,]/).map((s) => s.trim()).filter(Boolean);\n if (parts.length > 0 && parts.every((p) => isValidDocId(p))) {\n payload[key] = parts;\n }\n }\n break;\n }\n case 'media': {\n if (/^\\d+$/.test(rawVal.trim())) {\n payload[key] = parseInt(rawVal.trim(), 10);\n } else {\n try {\n const parsed = JSON.parse(rawVal);\n if (typeof parsed === 'number' || typeof parsed === 'object') {\n payload[key] = parsed;\n }\n } catch {}\n }\n break;\n }\n default:\n payload[key] = rawVal;\n }\n }\n\n try {\n if (mode === 'update') {\n if (!docId) {\n stats.skipped++;\n stats.errors.push({\n row: rowNumber,\n error: 'Missing or invalid documentId for Update mode. (Tip: Use Smart Auto-Detect mode to auto-add entries without document IDs).',\n });\n continue;\n }\n\n const existing = await findExistingDocument(strapi, uid, docId, rowLocale);\n\n if (!existing) {\n stats.skipped++;\n stats.errors.push({\n row: rowNumber,\n documentId: docId,\n error: `Document with ID \"${docId}\" not found in database.`,\n });\n continue;\n }\n\n const resolvedDocId = existing.documentId || docId;\n const mergedPayload = { ...payload };\n for (const key of Object.keys(payload)) {\n if (attrs[key]?.type === 'component' && typeof payload[key] === 'object' && payload[key] !== null) {\n mergedPayload[key] = deepMergeComponent((existing as any)[key], payload[key]);\n }\n }\n\n if (Object.keys(mergedPayload).length === 0) {\n stats.skipped++;\n stats.diffs.push({\n uid,\n collectionName: ct.info?.displayName || uid,\n documentId: resolvedDocId,\n label: (existing as any).title || (existing as any).name || `Entry #${resolvedDocId}`,\n attribute: '',\n oldValue: existing,\n newValue: {},\n status: 'skipped',\n message: `Skipped (no editable attributes in row ${rowNumber})`,\n });\n continue;\n }\n\n const updateArgs: any = {\n documentId: resolvedDocId,\n data: mergedPayload,\n };\n if (rowLocale) updateArgs.locale = rowLocale;\n\n await (strapi.documents(uid as any) as any).update(updateArgs);\n\n const isApproved = isDraftAndPublish && Boolean(existing?.publishedAt) && existing?.status !== 'modified';\n const shouldPublish = isDraftAndPublish && Boolean(publish) && (\n publishStrategy === 'all' ? true : isApproved\n );\n\n if (shouldPublish) {\n try {\n const pubArgs: any = { documentId: resolvedDocId };\n if (rowLocale) pubArgs.locale = rowLocale;\n await (strapi.documents(uid as any) as any).publish(pubArgs);\n } catch (pubErr) {\n strapi.log.warn(`[bulk-updater] Auto-publish failed for ${resolvedDocId}:`, pubErr);\n }\n }\n\n try {\n await recordContentHistoryVersion(strapi, {\n uid,\n documentId: resolvedDocId,\n userId: user?.id,\n statusOverride: shouldPublish ? 'published' : (isDraftAndPublish ? 'draft' : undefined),\n });\n } catch {}\n\n stats.updated++;\n for (const attrKey of Object.keys(payload)) {\n const oldVal = (existing as any)?.[attrKey] ?? null;\n const newVal = payload[attrKey];\n stats.diffs.push({\n uid,\n collectionName: ct.info?.displayName || uid,\n documentId: resolvedDocId,\n label: (existing as any).title || (existing as any).name || `Entry #${resolvedDocId}`,\n attribute: attrKey,\n oldValue: oldVal,\n newValue: newVal,\n status: 'updated',\n message: `Updated \"${attrKey}\" via CSV import (row ${rowNumber})`,\n });\n }\n } else if (mode === 'create_or_override') {\n let existing: any = null;\n if (docId) {\n existing = await findExistingDocument(strapi, uid, docId, rowLocale);\n }\n\n if (existing) {\n const resolvedDocId = existing.documentId || docId;\n const mergedPayload = { ...payload };\n for (const key of Object.keys(payload)) {\n if (attrs[key]?.type === 'component' && typeof payload[key] === 'object' && payload[key] !== null) {\n mergedPayload[key] = deepMergeComponent((existing as any)[key], payload[key]);\n }\n }\n\n const updateArgs: any = {\n documentId: resolvedDocId,\n data: mergedPayload,\n };\n if (rowLocale) updateArgs.locale = rowLocale;\n\n await (strapi.documents(uid as any) as any).update(updateArgs);\n\n const isApproved = isDraftAndPublish && Boolean(existing?.publishedAt) && existing?.status !== 'modified';\n const shouldPublish = isDraftAndPublish && Boolean(publish) && (\n publishStrategy === 'all' ? true : isApproved\n );\n\n if (shouldPublish) {\n try {\n const pubArgs: any = { documentId: resolvedDocId };\n if (rowLocale) pubArgs.locale = rowLocale;\n await (strapi.documents(uid as any) as any).publish(pubArgs);\n } catch (pubErr) {\n strapi.log.warn(`[bulk-updater] Auto-publish failed for ${resolvedDocId}:`, pubErr);\n }\n }\n\n try {\n await recordContentHistoryVersion(strapi, {\n uid,\n documentId: resolvedDocId,\n userId: user?.id,\n statusOverride: shouldPublish ? 'published' : (isDraftAndPublish ? 'draft' : undefined),\n });\n } catch {}\n\n stats.updated++;\n for (const attrKey of Object.keys(payload)) {\n const oldVal = (existing as any)?.[attrKey] ?? null;\n const newVal = payload[attrKey];\n stats.diffs.push({\n uid,\n collectionName: ct.info?.displayName || uid,\n documentId: resolvedDocId,\n label: (existing as any).title || (existing as any).name || `Entry #${resolvedDocId}`,\n attribute: attrKey,\n oldValue: oldVal,\n newValue: newVal,\n status: 'updated',\n message: `Overridden \"${attrKey}\" via CSV import (row ${rowNumber})`,\n });\n }\n continue;\n }\n\n const createArgs: any = { data: payload };\n if (rowLocale) createArgs.locale = rowLocale;\n const created: any = await strapi.documents(uid as any).create(createArgs);\n\n const newDocId = created?.documentId || docId;\n const shouldPublishNew = isDraftAndPublish && Boolean(publish) && (\n publishStrategy === 'all' ? true : false\n );\n\n if (shouldPublishNew && newDocId) {\n try {\n const pubArgs: any = { documentId: newDocId };\n if (rowLocale) pubArgs.locale = rowLocale;\n await (strapi.documents(uid as any) as any).publish(pubArgs);\n } catch (pubErr) {\n strapi.log.warn(`[bulk-updater] Auto-publish failed for ${newDocId}:`, pubErr);\n }\n }\n\n try {\n await recordContentHistoryVersion(strapi, {\n uid,\n documentId: newDocId,\n userId: user?.id,\n statusOverride: shouldPublishNew ? 'published' : (isDraftAndPublish ? 'draft' : undefined),\n });\n } catch {}\n\n stats.created++;\n if (!docId) {\n stats.newWithoutDocId++;\n }\n for (const attrKey of Object.keys(payload)) {\n stats.diffs.push({\n uid,\n collectionName: ct.info?.displayName || uid,\n documentId: newDocId,\n label: created?.title || created?.name || `New Entry #${newDocId}`,\n attribute: attrKey,\n oldValue: null,\n newValue: payload[attrKey],\n status: 'created',\n message: docId\n ? `Created \"${attrKey}\" via CSV import (row ${rowNumber})`\n : `Created \"${attrKey}\" as new entry (row ${rowNumber})`,\n });\n }\n } else {\n // Default: Smart Auto-Detect ('auto')\n let existing: any = null;\n if (docId) {\n existing = await findExistingDocument(strapi, uid, docId, rowLocale);\n }\n\n if (existing) {\n const resolvedDocId = existing.documentId || docId;\n const mergedPayload = { ...payload };\n for (const key of Object.keys(payload)) {\n if (attrs[key]?.type === 'component' && typeof payload[key] === 'object' && payload[key] !== null) {\n mergedPayload[key] = deepMergeComponent((existing as any)[key], payload[key]);\n }\n }\n\n const updateArgs: any = {\n documentId: resolvedDocId,\n data: mergedPayload,\n };\n if (rowLocale) updateArgs.locale = rowLocale;\n\n await (strapi.documents(uid as any) as any).update(updateArgs);\n\n const isApproved = isDraftAndPublish && Boolean(existing?.publishedAt) && existing?.status !== 'modified';\n const shouldPublish = isDraftAndPublish && Boolean(publish) && (\n publishStrategy === 'all' ? true : isApproved\n );\n\n if (shouldPublish) {\n try {\n const pubArgs: any = { documentId: resolvedDocId };\n if (rowLocale) pubArgs.locale = rowLocale;\n await (strapi.documents(uid as any) as any).publish(pubArgs);\n } catch (pubErr) {\n strapi.log.warn(`[bulk-updater] Auto-publish failed for ${resolvedDocId}:`, pubErr);\n }\n }\n\n try {\n await recordContentHistoryVersion(strapi, {\n uid,\n documentId: resolvedDocId,\n userId: user?.id,\n statusOverride: shouldPublish ? 'published' : (isDraftAndPublish ? 'draft' : undefined),\n });\n } catch {}\n\n stats.updated++;\n for (const attrKey of Object.keys(payload)) {\n const oldVal = (existing as any)?.[attrKey] ?? null;\n const newVal = payload[attrKey];\n stats.diffs.push({\n uid,\n collectionName: ct.info?.displayName || uid,\n documentId: resolvedDocId,\n label: (existing as any).title || (existing as any).name || `Entry #${resolvedDocId}`,\n attribute: attrKey,\n oldValue: oldVal,\n newValue: newVal,\n status: 'updated',\n message: `Updated \"${attrKey}\" via CSV import (row ${rowNumber})`,\n });\n }\n continue;\n }\n\n // Missing docId OR provided docId does not exist in DB -> create new\n const createArgs: any = { data: payload };\n if (rowLocale) createArgs.locale = rowLocale;\n const created: any = await strapi.documents(uid as any).create(createArgs);\n\n const newDocId = created?.documentId || docId;\n const shouldPublishNew = isDraftAndPublish && Boolean(publish) && (\n publishStrategy === 'all' ? true : false\n );\n\n if (shouldPublishNew && newDocId) {\n try {\n const pubArgs: any = { documentId: newDocId };\n if (rowLocale) pubArgs.locale = rowLocale;\n await (strapi.documents(uid as any) as any).publish(pubArgs);\n } catch (pubErr) {\n strapi.log.warn(`[bulk-updater] Auto-publish failed for ${newDocId}:`, pubErr);\n }\n }\n\n try {\n await recordContentHistoryVersion(strapi, {\n uid,\n documentId: newDocId,\n userId: user?.id,\n statusOverride: shouldPublishNew ? 'published' : (isDraftAndPublish ? 'draft' : undefined),\n });\n } catch {}\n\n stats.created++;\n if (!docId) {\n stats.newWithoutDocId++;\n }\n for (const attrKey of Object.keys(payload)) {\n stats.diffs.push({\n uid,\n collectionName: ct.info?.displayName || uid,\n documentId: newDocId,\n label: created?.title || created?.name || `New Entry #${newDocId}`,\n attribute: attrKey,\n oldValue: null,\n newValue: payload[attrKey],\n status: 'created',\n message: docId\n ? `Created \"${attrKey}\" as new entry (documentId \"${docId}\" not found in database - row ${rowNumber})`\n : `Created \"${attrKey}\" as new entry (no documentId provided in CSV - row ${rowNumber})`,\n });\n }\n }\n } catch (err: any) {\n stats.errors.push({\n row: rowNumber,\n documentId: docId || undefined,\n error: extractDetailedErrorMessage(err),\n });\n }\n }\n\n return stats;\n}\n\nasync function recordCsvAuditLog(\n strapi: Core.Strapi,\n ct: any,\n uid: string,\n batchId: string,\n stats: { total: number; created: number; updated: number; skipped: number; diffs: Array<any> },\n user?: any,\n publishOnApproval?: boolean,\n publishStrategy?: 'safe' | 'all',\n unreviewedConsent?: boolean\n) {\n if (stats.updated === 0 && stats.created === 0) return;\n\n try {\n const auditService = strapi.plugin('bulk-updater').service('audit');\n if (!auditService) return;\n\n const isEnabled = typeof auditService.isAuditEnabled === 'function'\n ? auditService.isAuditEnabled()\n : Boolean(auditService.getAuditConfig?.().enabled ?? true);\n\n if (!isEnabled) return;\n\n const userEmail = user?.email || 'admin@strapi.io';\n const userName = user ? `${user.firstname || ''} ${user.lastname || ''}`.trim() : 'CSV Importer';\n const collectionDisplayName = ct.info?.displayName || uid;\n const updatedDiffs = stats.diffs.filter(\n (d) => d.status === 'updated' || d.status === 'created'\n );\n const uniqueAttributes = Array.from(\n new Set(updatedDiffs.map((d) => d.attribute))\n ).filter(Boolean);\n const attrListStr = uniqueAttributes.length > 0 ? uniqueAttributes.join(', ') : 'fields';\n\n const batchAttribute = `CSV [${collectionDisplayName}]: ${attrListStr}`;\n\n let batchValue = '';\n if (updatedDiffs.length === 1) {\n const d = updatedDiffs[0];\n const newStr = d.newValue !== null && d.newValue !== undefined ? String(d.newValue) : '(empty)';\n batchValue = `\"${d.label}\": ${d.attribute} → \"${newStr}\"`;\n } else if (updatedDiffs.length > 1 && stats.updated === 1 && stats.created === 0) {\n const d = updatedDiffs[0];\n const changes = updatedDiffs\n .map((ud) => `${ud.attribute}: \"${ud.newValue ?? ''}\"`)\n .join(', ');\n batchValue = `\"${d.label}\": ${changes}`;\n } else {\n const sampleVal = updatedDiffs[0]\n ? ` (e.g. ${updatedDiffs[0].attribute}: \"${updatedDiffs[0].newValue ?? ''}\")`\n : '';\n batchValue = `${stats.updated} updated, ${stats.created} created in ${collectionDisplayName}${sampleVal}`;\n }\n\n const batchSummary = {\n batchId,\n attribute: batchAttribute,\n value: batchValue,\n updatedCount: stats.updated + stats.created,\n skippedCount: stats.skipped,\n totalTargets: stats.total,\n };\n\n const userObj = {\n email: userEmail || 'admin@strapi.io',\n firstname: userName || 'Admin',\n };\n\n if (typeof auditService.recordBatch === 'function') {\n await auditService.recordBatch(\n batchSummary,\n stats.diffs,\n userObj,\n publishOnApproval,\n publishStrategy,\n unreviewedConsent\n );\n } else if (typeof auditService.logOperation === 'function') {\n await auditService.logOperation({\n ...batchSummary,\n userEmail,\n userName,\n diffs: stats.diffs,\n });\n }\n } catch (auditErr) {\n strapi.log.warn('[bulk-updater] Failed logging CSV import audit:', auditErr);\n }\n}\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => ({\n /**\n * Generates a sample template CSV with schema attribute headers and sample values\n */\n async getTemplateCsv(uid: string) {\n const ct = strapi.contentTypes[uid];\n if (!ct) {\n throw new Error(`Content type ${uid} not found`);\n }\n\n const attrs = ct.attributes || {};\n const excluded = ['createdAt', 'updatedAt', 'publishedAt', 'createdBy', 'updatedBy', 'localizations'];\n\n // Base columns: documentId (optional for create, required for update)\n const headers = ['documentId'];\n const sampleRow: string[] = ['(Leave empty to create new, or enter existing docId)'];\n\n for (const [attrName, attrDef] of Object.entries(attrs) as any[]) {\n if (excluded.includes(attrName)) continue;\n if (attrDef.type === 'relation') continue;\n if (attrDef.type === 'component' || attrDef.type === 'dynamiczone') continue;\n\n headers.push(attrName);\n let sampleVal = '';\n switch (attrDef.type) {\n case 'string':\n case 'text':\n case 'richtext':\n sampleVal = `Sample ${attrName}`;\n break;\n case 'integer':\n case 'biginteger':\n case 'float':\n case 'decimal':\n sampleVal = '10';\n break;\n case 'boolean':\n sampleVal = 'true';\n break;\n case 'email':\n sampleVal = 'sample@example.com';\n break;\n case 'enumeration':\n sampleVal = attrDef.enum?.[0] || 'option1';\n break;\n case 'customField':\n sampleVal = 'value';\n break;\n default:\n sampleVal = 'sample';\n }\n sampleRow.push(sampleVal);\n }\n\n const csvContent =\n '\\uFEFF' +\n headers.map(escapeCsvValue).join(',') +\n '\\r\\n' +\n sampleRow.map(escapeCsvValue).join(',') +\n '\\r\\n';\n\n return {\n filename: `${ct.info?.singularName || 'template'}_template.csv`,\n csvContent,\n headers,\n };\n },\n\n /**\n * Exports entries of a collection to CSV with deep nested component support,\n * RFC-4180 CRLF line endings, and UTF-8 BOM for 100% Microsoft Excel compatibility.\n */\n async exportCollectionCsv(\n uid: string,\n options: {\n search?: string;\n attribute?: string;\n filterOperator?: string;\n filterQuery?: string;\n limit?: number;\n documentIds?: string[];\n } = {}\n ) {\n const ct = strapi.contentTypes[uid];\n if (!ct) {\n throw new Error(`Content type ${uid} not found`);\n }\n\n const allComponents = strapi.components || {};\n\n // 1. Discover all exportable fields, including nested components\n const fields = discoverExportFields(ct, allComponents);\n\n // 2. Build database query filters\n const filters: Record<string, any> = {};\n const { attribute, filterOperator, filterQuery, search, documentIds } = options;\n\n // Filter by specific selected document IDs if provided\n if (documentIds && Array.isArray(documentIds) && documentIds.length > 0) {\n filters.documentId = { $in: documentIds };\n }\n\n // Apply attribute condition filter with nested component support\n if (attribute && filterOperator && filterOperator !== 'none') {\n const isNested = attribute.includes('.');\n if (filterOperator === 'empty') {\n if (isNested) {\n const [parent, child] = attribute.split('.');\n filters[parent] = { [child]: { $null: true } };\n } else {\n filters[attribute] = { $null: true };\n }\n } else if (filterOperator === 'not_empty') {\n if (isNested) {\n const [parent, child] = attribute.split('.');\n filters[parent] = { [child]: { $notNull: true } };\n } else {\n filters[attribute] = { $notNull: true };\n }\n } else if (filterQuery !== undefined && filterQuery !== '') {\n const opMap: Record<string, string> = {\n equals: '$eq',\n notEquals: '$ne',\n contains: '$containsi',\n notContains: '$notContainsi',\n startsWith: '$startsWith',\n endsWith: '$endsWith',\n };\n const strapiOp = opMap[filterOperator] || '$eq';\n if (isNested) {\n const [parent, child] = attribute.split('.');\n filters[parent] = { [child]: { [strapiOp]: filterQuery } };\n } else {\n filters[attribute] = { [strapiOp]: filterQuery };\n }\n }\n }\n\n // Text search filter\n if (search && search.trim() !== '') {\n const q = search.trim();\n const searchConditions: any[] = [];\n const searchFields = ['name', 'title', 'email', 'slug', 'description'].filter(\n (f) => ct.attributes?.[f] && ['string', 'text', 'email'].includes(ct.attributes[f].type)\n );\n\n for (const field of searchFields) {\n searchConditions.push({ [field]: { $containsi: q } });\n }\n\n if (searchConditions.length > 0) {\n if (filters && Object.keys(filters).length > 0) {\n filters.$and = [{ $or: searchConditions }];\n } else {\n filters.$or = searchConditions;\n }\n }\n }\n\n // 3. Build deep populate tree so nested components and relations are retrieved\n const deepPopulate = buildDeepPopulate(ct.attributes || {}, allComponents);\n\n // 4. Retrieve entries and generate RFC-4180 CRLF rows with UTF-8 BOM\n const lines: string[] = [];\n lines.push(fields.map((f) => escapeCsvValue(f.key)).join(','));\n\n let totalExported = 0;\n const maxLimit = options.limit && options.limit > 0 ? options.limit : Infinity;\n const CHUNK_SIZE = 1000;\n\n if (ct.kind === 'singleType') {\n const findFirstArgs: any = {};\n if (deepPopulate) {\n findFirstArgs.populate = deepPopulate;\n }\n const doc = await (strapi.documents(uid as any) as any).findFirst(findFirstArgs);\n if (doc) {\n const rowValues = fields.map((f) => escapeCsvValue(getNestedExportValue(doc, f.key)));\n lines.push(rowValues.join(','));\n totalExported = 1;\n }\n } else {\n let currentPage = 1;\n let hasMore = true;\n\n while (hasMore && totalExported < maxLimit) {\n const remaining = maxLimit - totalExported;\n const currentBatchLimit = Math.min(CHUNK_SIZE, remaining);\n\n const findPageArgs: any = {\n filters: Object.keys(filters).length > 0 ? filters : undefined,\n page: currentPage,\n pageSize: currentBatchLimit,\n sort: { createdAt: 'desc' },\n };\n if (deepPopulate) {\n findPageArgs.populate = deepPopulate;\n }\n\n const chunkEntries: any[] = await (strapi.documents(uid as any) as any).findMany(findPageArgs);\n\n if (!chunkEntries || chunkEntries.length === 0) {\n hasMore = false;\n break;\n }\n\n for (const entry of chunkEntries) {\n const rowValues = fields.map((f) => escapeCsvValue(getNestedExportValue(entry, f.key)));\n lines.push(rowValues.join(','));\n totalExported++;\n if (totalExported >= maxLimit) {\n hasMore = false;\n break;\n }\n }\n\n if (chunkEntries.length < currentBatchLimit) {\n hasMore = false;\n } else {\n currentPage++;\n }\n }\n }\n\n // Prepend UTF-8 BOM and terminate lines with CRLF for seamless Excel import\n const csvContent = '\\uFEFF' + lines.join('\\r\\n') + '\\r\\n';\n const filename = `${ct.info?.singularName || uid}_export_${new Date().toISOString().slice(0, 10)}.csv`;\n\n return {\n filename,\n csvContent,\n count: totalExported,\n fields: fields.map((f) => f.key),\n };\n },\n\n /**\n * Exports violations of a specific rule directly into a CSV\n */\n async exportViolationsCsv(ruleId: string) {\n const validationRulesService = strapi.plugin('bulk-updater').service('validationRules');\n const scanReport = await validationRulesService.scanViolations(ruleId);\n\n const headers = [\n 'collectionUid',\n 'collectionName',\n 'documentId',\n 'entryLabel',\n 'targetField',\n 'violatingOption',\n 'foundCount',\n 'maxAllowed',\n 'directEditorUrl',\n ];\n\n const lines: string[] = [];\n lines.push(headers.map(escapeCsvValue).join(','));\n\n for (const v of scanReport.violations) {\n const row = [\n v.uid,\n v.collectionDisplayName,\n v.documentId,\n v.entryLabel,\n scanReport.rule.targetField,\n v.violatingOption,\n v.foundCount,\n v.maxAllowed,\n v.editUrl,\n ];\n lines.push(row.map(escapeCsvValue).join(','));\n }\n\n const safeRuleName = scanReport.rule.name.replace(/[^a-zA-Z0-9_-]/g, '_');\n const filename = `violations_${safeRuleName}_${new Date().toISOString().slice(0, 10)}.csv`;\n\n return {\n filename,\n csvContent: '\\uFEFF' + lines.join('\\r\\n') + '\\r\\n',\n count: scanReport.violations.length,\n ruleName: scanReport.rule.name,\n };\n },\n\n /**\n * Bulk Export: Exports selected entries across multiple collections or a multi-collection batch.\n */\n async exportBulkCsv(selectedEntries: Array<{ uid: string; documentId: string }>) {\n if (!selectedEntries || selectedEntries.length === 0) {\n throw new Error('No entries selected for bulk export');\n }\n\n // Group selected documentIds by collection uid\n const byUid: Record<string, string[]> = {};\n for (const item of selectedEntries) {\n if (!byUid[item.uid]) byUid[item.uid] = [];\n byUid[item.uid].push(item.documentId);\n }\n\n const uids = Object.keys(byUid);\n\n // If all entries belong to a single collection, export full collection schema with deep fields\n if (uids.length === 1) {\n const uid = uids[0];\n return await this.exportCollectionCsv(uid, { documentIds: byUid[uid], limit: 0 });\n }\n\n // Multi-collection unified export\n const rows: string[] = [];\n const headers = [\n 'Collection UID',\n 'Collection Name',\n 'Document ID',\n 'Record Title / Name',\n 'Primary Identifier',\n 'Created At',\n 'Updated At',\n 'Published Status',\n ];\n rows.push(headers.map(escapeCsvValue).join(','));\n\n let totalExported = 0;\n\n for (const uid of uids) {\n const ct = strapi.contentTypes[uid];\n if (!ct) continue;\n const displayName = ct.info?.displayName || uid;\n const docIds = byUid[uid];\n\n const entries = await (strapi.documents(uid as any) as any).findMany({\n filters: { documentId: { $in: docIds } },\n limit: docIds.length,\n });\n\n for (const entry of (entries || []) as any[]) {\n const titleOrName = entry.title || entry.name || entry.subject || entry.email || `Entry #${entry.documentId}`;\n const identifier = entry.slug || entry.email || entry.username || entry.documentId;\n const isPublished = Boolean(entry.publishedAt);\n\n const row = [\n uid,\n displayName,\n entry.documentId,\n titleOrName,\n identifier,\n entry.createdAt || '',\n entry.updatedAt || '',\n isPublished ? 'Published' : 'Draft',\n ];\n rows.push(row.map(escapeCsvValue).join(','));\n totalExported++;\n }\n }\n\n const filename = `bulk_export_selected_${totalExported}_entries_${new Date().toISOString().slice(0, 10)}.csv`;\n return {\n filename,\n csvContent: '\\uFEFF' + rows.join('\\r\\n') + '\\r\\n',\n count: totalExported,\n isMultiCollection: true,\n };\n },\n\n /**\n * Imports a single chunk of CSV rows (for large dataset streaming/batching).\n * Aggregates stats across chunks and writes unified audit trail on the final chunk.\n */\n async importChunk(\n uid: string,\n rows: Array<Record<string, string>>,\n options: {\n batchId?: string;\n isFirstChunk?: boolean;\n isLastChunk?: boolean;\n startRowNumber?: number;\n mode?: 'auto' | 'update' | 'create_or_override';\n publish?: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n user?: any;\n }\n ) {\n const ct = strapi.contentTypes[uid];\n if (!ct) {\n throw new Error(`Content type ${uid} not found`);\n }\n\n cleanupStaleSessions();\n\n const batchId = options.batchId || `csv_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n let session = csvImportSessions.get(batchId);\n\n if (!session || options.isFirstChunk) {\n session = {\n batchId,\n uid,\n createdAt: Date.now(),\n total: 0,\n created: 0,\n updated: 0,\n skipped: 0,\n newWithoutDocId: 0,\n errors: [],\n diffs: [],\n publishStrategy: options.publishStrategy,\n unreviewedConsent: options.unreviewedConsent,\n };\n csvImportSessions.set(batchId, session);\n }\n\n const startRowNumber = options.startRowNumber || (session.total + 2);\n const chunkStats = await processCsvRows(strapi, ct, uid, rows || [], startRowNumber, options);\n\n session.total += chunkStats.total;\n session.created += chunkStats.created;\n session.updated += chunkStats.updated;\n session.skipped += chunkStats.skipped;\n session.newWithoutDocId += chunkStats.newWithoutDocId;\n session.errors.push(...chunkStats.errors);\n session.diffs.push(...chunkStats.diffs);\n\n if (options.isLastChunk) {\n await recordCsvAuditLog(\n strapi,\n ct,\n uid,\n batchId,\n session,\n options.user,\n options.publish !== false,\n session.publishStrategy || options.publishStrategy,\n session.unreviewedConsent ?? options.unreviewedConsent\n );\n\n try {\n const bulkService = strapi.plugin('bulk-updater').service('bulkUpdater');\n if (bulkService && (bulkService as any).invalidateCollectionCache) {\n (bulkService as any).invalidateCollectionCache(uid);\n }\n } catch {}\n\n const aggregateStats = {\n total: session.total,\n created: session.created,\n updated: session.updated,\n skipped: session.skipped,\n newWithoutDocId: session.newWithoutDocId,\n errors: session.errors,\n diffs: session.diffs,\n };\n\n csvImportSessions.delete(batchId);\n\n return {\n success: true,\n batchId,\n chunkStats,\n stats: aggregateStats,\n isFinished: true,\n };\n }\n\n return {\n success: true,\n batchId,\n chunkStats,\n isFinished: false,\n };\n },\n\n /**\n * Imports CSV records to update existing records or insert/override records (single payload).\n */\n async importCsv(\n uid: string,\n csvText: string,\n options: {\n mode?: 'auto' | 'update' | 'create_or_override';\n publish?: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n user?: any;\n }\n ) {\n const ct = strapi.contentTypes[uid];\n if (!ct) {\n throw new Error(`Content type ${uid} not found`);\n }\n\n const parsedRows = parseCsv(csvText);\n if (!parsedRows || parsedRows.length === 0) {\n throw new Error('CSV is empty or could not be parsed.');\n }\n\n const batchId = `csv_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const stats = await processCsvRows(strapi, ct, uid, parsedRows, 2, options);\n\n try {\n const bulkService = strapi.plugin('bulk-updater').service('bulkUpdater');\n if (bulkService && (bulkService as any).invalidateCollectionCache) {\n (bulkService as any).invalidateCollectionCache(uid);\n }\n } catch {}\n\n await recordCsvAuditLog(\n strapi,\n ct,\n uid,\n batchId,\n stats,\n options.user,\n options.publish !== false,\n options.publishStrategy,\n options.unreviewedConsent\n );\n\n return {\n success: true,\n batchId,\n stats,\n };\n },\n\n /**\n * Executes a pending CSV batch approved by Checker or queued for off-peak execution\n */\n async executeCsvPendingBatch(\n uid: string,\n rows: Array<Record<string, string>>,\n batchId: string,\n options: {\n mode?: 'auto' | 'update' | 'create_or_override';\n publish?: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n user?: any;\n } = {},\n checkerUser?: any\n ) {\n const ct = strapi.contentTypes[uid];\n if (!ct) {\n throw new Error(`Content type ${uid} not found`);\n }\n\n const effectiveUser = checkerUser || options.user;\n const stats = await processCsvRows(strapi, ct, uid, rows || [], 2, {\n ...options,\n user: effectiveUser,\n });\n\n await recordCsvAuditLog(\n strapi,\n ct,\n uid,\n batchId,\n stats,\n effectiveUser,\n options.publish !== false,\n options.publishStrategy,\n options.unreviewedConsent\n );\n\n try {\n const bulkService = strapi.plugin('bulk-updater').service('bulkUpdater');\n if (bulkService && (bulkService as any).invalidateCollectionCache) {\n (bulkService as any).invalidateCollectionCache(uid);\n }\n } catch {}\n\n return {\n success: true,\n batchId,\n stats,\n };\n },\n\n /**\n * Pre-Flight Dry-Run Validation: Non-mutating analysis verifying document existence,\n * data types, schema integrity, and quota rule violations before execution.\n */\n async validatePreflight(\n uid: string,\n rows: Array<Record<string, string>>,\n options: {\n mode?: 'auto' | 'update' | 'create_or_override';\n } = {}\n ) {\n const ct = strapi.contentTypes[uid];\n if (!ct) {\n throw new Error(`Content type ${uid} not found`);\n }\n\n const { mode = 'auto' } = options;\n const attrs = ct.attributes || {};\n\n let validationRulesService: any = null;\n let activeRules: any[] = [];\n try {\n validationRulesService = strapi.plugin('bulk-updater').service('validationRules');\n if (validationRulesService) {\n const rulesRes = await validationRulesService.getRules();\n activeRules = (rulesRes || []).filter((r: any) => r.enabled);\n }\n } catch {}\n\n let validRows = 0;\n let estimatedUpdates = 0;\n let estimatedCreates = 0;\n const isDraftAndPublish = Boolean(ct.options?.draftAndPublish);\n const lifecycleStats = {\n isDraftAndPublish,\n totalChecked: 0,\n published: 0,\n modified: 0,\n draft: 0,\n unreviewedCount: 0,\n };\n const errors: Array<{ row: number; documentId?: string; error: string }> = [];\n const warnings: Array<{ row: number; documentId?: string; warning: string }> = [];\n\n for (let i = 0; i < rows.length; i++) {\n const rowNumber = i + 2;\n const row = rows[i];\n const docId = extractDocId(row);\n const rowLocale = extractLocale(row);\n let rowHasError = false;\n\n // 1. Document Existence Check\n let existing: any = null;\n if (docId) {\n existing = await findExistingDocument(strapi, uid, docId, rowLocale);\n }\n\n if (existing && isDraftAndPublish) {\n lifecycleStats.totalChecked++;\n const isApproved = Boolean(existing.publishedAt) && existing.status !== 'modified';\n if (isApproved) {\n lifecycleStats.published++;\n } else if (existing.status === 'modified') {\n lifecycleStats.modified++;\n lifecycleStats.unreviewedCount++;\n } else {\n lifecycleStats.draft++;\n lifecycleStats.unreviewedCount++;\n }\n }\n\n if (mode === 'update') {\n if (!docId) {\n errors.push({\n row: rowNumber,\n error: 'Missing or invalid documentId for Update Only mode.',\n });\n rowHasError = true;\n } else if (!existing) {\n errors.push({\n row: rowNumber,\n documentId: docId,\n error: `Document with ID \"${docId}\" not found in database.`,\n });\n rowHasError = true;\n } else {\n estimatedUpdates++;\n }\n } else if (mode === 'create_or_override') {\n if (existing) {\n estimatedUpdates++;\n } else {\n estimatedCreates++;\n }\n } else {\n // Smart Auto-Detect\n if (existing) {\n estimatedUpdates++;\n } else {\n estimatedCreates++;\n if (docId) {\n warnings.push({\n row: rowNumber,\n documentId: docId,\n warning: `Document ID \"${docId}\" not found in DB; will create as a new entry.`,\n });\n }\n }\n }\n\n // 2. Schema Type Validation\n for (const [colKey, rawVal] of Object.entries(row)) {\n if (!rawVal || rawVal.trim() === '') continue;\n const normalizedKey = colKey.toLowerCase().replace(/[\\s_-]/g, '');\n if (SYSTEM_FIELD_KEYS.has(normalizedKey)) continue;\n\n let attrDef = attrs[colKey];\n if (!attrDef && !colKey.includes('.')) {\n const matchKey = Object.keys(attrs).find(\n (k) => k.toLowerCase() === colKey.toLowerCase() || k.toLowerCase() === colKey.toLowerCase().replace(/\\s+/g, '')\n );\n if (matchKey) attrDef = attrs[matchKey];\n }\n\n if (attrDef) {\n if (attrDef.type === 'integer' || attrDef.type === 'biginteger') {\n const num = parseInt(rawVal, 10);\n if (isNaN(num)) {\n errors.push({\n row: rowNumber,\n documentId: docId || undefined,\n error: `Column \"${colKey}\" expects an integer, received: \"${rawVal}\"`,\n });\n rowHasError = true;\n }\n } else if (attrDef.type === 'float' || attrDef.type === 'decimal') {\n const num = parseFloat(rawVal);\n if (isNaN(num)) {\n errors.push({\n row: rowNumber,\n documentId: docId || undefined,\n error: `Column \"${colKey}\" expects a numeric float/decimal, received: \"${rawVal}\"`,\n });\n rowHasError = true;\n }\n } else if (attrDef.type === 'enumeration' && Array.isArray(attrDef.enum)) {\n if (!attrDef.enum.includes(rawVal.trim())) {\n warnings.push({\n row: rowNumber,\n documentId: docId || undefined,\n warning: `Column \"${colKey}\" value \"${rawVal}\" is not in defined enum options: [${attrDef.enum.join(', ')}]`,\n });\n }\n } else if (attrDef.type === 'json') {\n try {\n JSON.parse(rawVal);\n } catch {\n warnings.push({\n row: rowNumber,\n documentId: docId || undefined,\n warning: `Column \"${colKey}\" is type JSON but contains non-JSON text.`,\n });\n }\n }\n }\n\n // 3. Quota Rules Scan\n if (activeRules.length > 0) {\n for (const rule of activeRules) {\n if (rule.collectionUid && rule.collectionUid !== '*' && rule.collectionUid !== uid) continue;\n if (rule.includeRichTextHtml && (rawVal.includes('<h') || rawVal.includes('# '))) {\n const headings = extractHeadingsFromRichText(rawVal);\n for (const [tag, count] of Object.entries(headings)) {\n const max = rule.quotas?.[tag.toLowerCase()];\n if (max !== undefined && count > max) {\n warnings.push({\n row: rowNumber,\n documentId: docId || undefined,\n warning: `Rule \"${rule.name}\" quota warning: column \"${colKey}\" contains ${count} \"${tag.toUpperCase()}\" headings (maximum allowed: ${max}).`,\n });\n }\n }\n }\n }\n }\n }\n\n if (!rowHasError) {\n validRows++;\n }\n }\n\n return {\n success: true,\n totalRows: rows.length,\n validRows,\n estimatedUpdates,\n estimatedCreates,\n lifecycleStats,\n hasErrors: errors.length > 0,\n hasWarnings: warnings.length > 0,\n errors: errors.slice(0, 100),\n warnings: warnings.slice(0, 100),\n totalErrorCount: errors.length,\n totalWarningCount: warnings.length,\n };\n },\n\n /**\n * Submits a CSV batch with Guardrails: Maker-Checker (4-Eyes), Execution Windows, Off-Peak Scheduling\n */\n async submitBatch(\n uid: string,\n rows: Array<Record<string, string>>,\n options: {\n executionMode?: 'immediate' | 'queue_offpeak' | 'maker_checker';\n makerNotes?: string;\n forceImmediate?: boolean;\n mode?: 'auto' | 'update' | 'create_or_override';\n publish?: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n unreviewedCount?: number;\n user?: any;\n } = {}\n ) {\n const ct = strapi.contentTypes[uid];\n if (!ct) {\n throw new Error(`Content type ${uid} not found`);\n }\n\n if (!rows || rows.length === 0) {\n throw new Error('No CSV records provided for batch submission.');\n }\n\n const {\n executionMode = 'immediate',\n makerNotes = '',\n forceImmediate = false,\n mode = 'auto',\n publish = true,\n publishStrategy = 'safe',\n unreviewedConsent = false,\n unreviewedCount = 0,\n user,\n } = options;\n\n const executionConfig = getExecutionWindowConfig(strapi);\n const { isBusinessHours, policyMessage } = checkBusinessHours(executionConfig);\n const collectionDisplayName = ct.info?.displayName || uid;\n\n // 1. Enterprise Maker-Checker Flow (4-Eyes Approval Principle)\n if (executionMode === 'maker_checker') {\n const batchId = `csv_batch_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const batch: PendingBatch = {\n id: batchId,\n createdAt: new Date().toISOString(),\n createdBy: user\n ? {\n id: user.id,\n email: user.email,\n firstname: user.firstname,\n lastname: user.lastname,\n username: user.username,\n }\n : { email: 'admin@system.local' },\n payload: {\n action: 'csv_import',\n uid,\n rows,\n options: {\n mode,\n publish,\n publishStrategy,\n unreviewedConsent,\n user,\n },\n attribute: `CSV Import: ${collectionDisplayName}`,\n value: `${rows.length} rows (${mode} mode)`,\n publishOnApproval: publish,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n },\n summary: {\n attribute: `CSV Import: ${collectionDisplayName}`,\n value: `${rows.length} rows (${mode} mode)`,\n totalTargets: rows.length,\n collectionBreakdown: { [collectionDisplayName]: rows.length },\n publishOnApproval: publish,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n },\n status: 'pending_approval',\n executionMode: 'maker_checker',\n makerNotes,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n };\n\n registerPendingBatch(batch, {\n id: batchId,\n createdAt: batch.createdAt,\n createdBy: batch.createdBy,\n status: 'pending_approval',\n executionMode: 'maker_checker',\n attribute: `CSV Import: ${collectionDisplayName}`,\n value: `${rows.length} rows (${mode} mode)`,\n totalTargets: rows.length,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: publish,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n makerNotes,\n results: [],\n });\n\n return {\n success: true,\n pending: true,\n batchId,\n status: 'pending_approval',\n message: 'CSV batch submitted for Checker authorization (4-Eyes Maker-Checker Workflow).',\n batch,\n };\n }\n\n // 2. Off-Peak Queued Batch\n if (executionMode === 'queue_offpeak') {\n const batchId = `csv_batch_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const batch: PendingBatch = {\n id: batchId,\n createdAt: new Date().toISOString(),\n createdBy: user\n ? {\n id: user.id,\n email: user.email,\n firstname: user.firstname,\n lastname: user.lastname,\n username: user.username,\n }\n : { email: 'admin@system.local' },\n payload: {\n action: 'csv_import',\n uid,\n rows,\n options: {\n mode,\n publish,\n publishStrategy,\n unreviewedConsent,\n user,\n },\n attribute: `CSV Import: ${collectionDisplayName}`,\n value: `${rows.length} rows (${mode} mode)`,\n publishOnApproval: publish,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n },\n summary: {\n attribute: `CSV Import: ${collectionDisplayName}`,\n value: `${rows.length} rows (${mode} mode)`,\n totalTargets: rows.length,\n collectionBreakdown: { [collectionDisplayName]: rows.length },\n publishOnApproval: publish,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n },\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n makerNotes,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n };\n\n registerPendingBatch(batch, {\n id: batchId,\n createdAt: batch.createdAt,\n createdBy: batch.createdBy,\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n attribute: `CSV Import: ${collectionDisplayName}`,\n value: `${rows.length} rows (${mode} mode)`,\n totalTargets: rows.length,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: publish,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n makerNotes,\n results: [],\n });\n\n return {\n success: true,\n pending: true,\n batchId,\n status: 'queued_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n message: `CSV batch queued for server off-peak maintenance window (${executionConfig.offPeakStartTime}).`,\n batch,\n };\n }\n\n // 3. Peak Business Hours Restriction Active (Auto-Queue)\n if (executionConfig.enabled && executionConfig.autoQueueDuringBusinessHours && isBusinessHours && !forceImmediate) {\n const batchId = `csv_batch_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const batch: PendingBatch = {\n id: batchId,\n createdAt: new Date().toISOString(),\n createdBy: user\n ? {\n id: user.id,\n email: user.email,\n firstname: user.firstname,\n lastname: user.lastname,\n username: user.username,\n }\n : { email: 'admin@system.local' },\n payload: {\n action: 'csv_import',\n uid,\n rows,\n options: {\n mode,\n publish,\n publishStrategy,\n unreviewedConsent,\n user,\n },\n attribute: `CSV Import: ${collectionDisplayName}`,\n value: `${rows.length} rows (${mode} mode)`,\n publishOnApproval: publish,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n },\n summary: {\n attribute: `CSV Import: ${collectionDisplayName}`,\n value: `${rows.length} rows (${mode} mode)`,\n totalTargets: rows.length,\n collectionBreakdown: { [collectionDisplayName]: rows.length },\n publishOnApproval: publish,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n },\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n makerNotes: 'Automatically queued due to peak business hours restriction.',\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n };\n\n registerPendingBatch(batch, {\n id: batchId,\n createdAt: batch.createdAt,\n createdBy: batch.createdBy,\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n attribute: `CSV Import: ${collectionDisplayName}`,\n value: `${rows.length} rows (${mode} mode)`,\n totalTargets: rows.length,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: publish,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n policyMessage,\n makerNotes: 'Automatically queued due to peak business hours restriction.',\n results: [],\n });\n\n return {\n success: true,\n pending: true,\n batchId,\n status: 'queued_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n message: policyMessage,\n batch,\n };\n }\n\n // 4. Immediate execution allowed: Signal frontend to proceed with chunked execution\n return {\n success: true,\n pending: false,\n executeNow: true,\n };\n },\n});\n","import routes from './routes';\nimport contentTypes from './content-types';\nimport bulkUpdaterController from './controllers/bulk-updater';\nimport auditController from './controllers/audit';\nimport validationRulesController from './controllers/validation-rules';\nimport csvController from './controllers/csv';\nimport bulkUpdaterService from './services/bulk-updater';\nimport auditService from './services/audit';\nimport validationRulesService, { extractHeadingsFromRichText, matchesPath, cleanKey } from './services/validation-rules';\nimport csvService from './services/csv';\nimport contentHistoryService, { recordContentHistoryVersion } from './services/content-history';\n\nimport { errors } from '@strapi/utils';\n\nfunction createValidationError(ruleName: string, detailMsg: string, targetField: string) {\n const fullMessage = `Validation Error (${ruleName}): ${detailMsg}`;\n const ApplicationErrorClass: any = (errors as any)?.ApplicationError || Error;\n\n const err = new ApplicationErrorClass(fullMessage);\n err.name = 'ApplicationError';\n err.status = 400;\n (err as any).isQuotaViolation = true;\n (err as any).targetField = targetField;\n (err as any).details = {};\n return err;\n}\n\nexport default {\n register({ strapi }: { strapi: any }) {\n // Register the server definition for custom field plugin::bulk-updater.scoped-select\n strapi.customFields.register({\n name: 'scoped-select',\n plugin: 'bulk-updater',\n type: 'string',\n });\n },\n bootstrap({ strapi }: { strapi: any }) {\n // Intercept quota validation errors to return HTTP 400 ApplicationError so Strapi's admin UI displays specific danger banner\n strapi.server.use(async (ctx: any, next: any) => {\n try {\n await next();\n } catch (err: any) {\n const isQuotaErr =\n err?.isQuotaViolation ||\n err?.name === 'ApplicationError' ||\n err?.name === 'ValidationError' ||\n (typeof err?.message === 'string' &&\n (err.message.startsWith('Validation Error') || err.message.includes('cannot appear more than')));\n\n if (isQuotaErr) {\n ctx.status = 400;\n ctx.body = {\n data: null,\n error: {\n status: 400,\n name: 'ApplicationError',\n message: err.message,\n details: {},\n },\n };\n return;\n }\n throw err;\n }\n });\n\n // Register Document Service middleware to enforce cross-component quotas on the backend\n strapi.documents.use(async (context: any, next: any) => {\n const params = context.params as any;\n if (['create', 'update'].includes(context.action)) {\n const data = params?.data;\n\n if (data && typeof data === 'object') {\n // 1. Fetch active UI-configured validation rules from the plugin store\n let activeUiRules: any[] = [];\n try {\n const rulesService = strapi.plugin('bulk-updater').service('validationRules');\n if (rulesService) {\n const allRules = await rulesService.getRules();\n activeUiRules = allRules.filter((r: any) => r.enabled);\n }\n } catch (err) {\n strapi.log.warn('[bulk-updater] Failed to fetch active UI validation rules:', err);\n }\n\n // 2. Discover attributes from schemas as fallback if not in UI rules\n // Filter UI rules scoped to this collection type (or '*' for global, with flexible UID / name matching)\n const effectiveRules: Array<{\n id: string;\n name: string;\n collectionUid?: string;\n targetField: string;\n quotas: Record<string, number>;\n includeRichTextHtml?: boolean;\n richTextFields?: string[];\n }> = [\n ...activeUiRules\n .filter((r: any) => {\n if (!r.collectionUid || r.collectionUid === '*') return true;\n if (r.collectionUid === context.uid) return true;\n const cleanRuleCol = cleanKey(r.collectionUid);\n const cleanCtxCol = cleanKey(context.uid);\n return cleanCtxCol.includes(cleanRuleCol) || cleanRuleCol.includes(cleanCtxCol);\n })\n .map((r: any) => ({\n id: r.id || r.targetField,\n name: r.name || r.targetField,\n collectionUid: r.collectionUid || '*',\n targetField: r.targetField,\n quotas: r.quotas || {},\n includeRichTextHtml: Boolean(r.includeRichTextHtml),\n richTextFields: r.richTextFields || [],\n })),\n ];\n\n const allComponents = strapi.components || {};\n for (const comp of Object.values(allComponents) as any[]) {\n const attrs = comp.attributes || {};\n for (const [attrName, attrDef] of Object.entries(attrs) as any[]) {\n if (\n attrDef.type === 'customField' &&\n (attrDef.customField === 'plugin::bulk-updater.scoped-select' ||\n attrDef.customField === 'global::scoped-select') &&\n !effectiveRules.some((r) => matchesPath(attrName, attrName, r.targetField))\n ) {\n const quotas = attrDef.options?.quotas || {};\n const items = attrDef.options?.items || [];\n const itemQuotas: Record<string, number> = {};\n\n for (const item of items) {\n if (typeof item.maxAllowed === 'number' && item.maxAllowed > 0) {\n itemQuotas[item.value] = item.maxAllowed;\n }\n }\n\n effectiveRules.push({\n id: `schema_${attrName}`,\n name: `${attrName} quota rule`,\n collectionUid: '*',\n targetField: attrName,\n quotas: {\n h1: 1,\n h2: 3,\n ...itemQuotas,\n ...quotas,\n },\n includeRichTextHtml: true,\n richTextFields: [],\n });\n }\n }\n }\n\n const structuredCounts: Record<string, Record<string, number>> = {};\n const richTextCounts: Record<string, number> = { h1: 0, h2: 0, h3: 0, h4: 0, h5: 0, h6: 0 };\n\n function scanDataTree(obj: any, currentPath = '') {\n if (!obj || typeof obj !== 'object') return;\n const compName = typeof obj.__component === 'string' ? obj.__component : '';\n\n for (const key of Object.keys(obj)) {\n if (key === '__component') continue;\n const val = obj[key];\n const newPath = currentPath ? `${currentPath}.${key}` : key;\n const normalizedPath = newPath.replace(/\\.\\d+/g, '');\n\n const compPath = compName\n ? (currentPath ? `${currentPath}.${compName}.${key}` : `${compName}.${key}`).replace(/\\.\\d+/g, '')\n : '';\n\n // Check structured rules matching targetField (supports dot notation like st-featured.titleHeadingStyle.titleStyle or titleHeadingStyle.titleStyle)\n for (const rule of effectiveRules) {\n const isMatch = matchesPath(normalizedPath, key, rule.targetField) ||\n (compPath ? matchesPath(compPath, key, rule.targetField) : false);\n\n if (isMatch && typeof val === 'string' && val.trim()) {\n const lowerVal = val.toLowerCase().trim();\n structuredCounts[rule.id] = structuredCounts[rule.id] || {};\n structuredCounts[rule.id][lowerVal] = (structuredCounts[rule.id][lowerVal] || 0) + 1;\n }\n }\n\n // Check rich text HTML / Markdown / Blocks content\n if (typeof val === 'string' && (val.includes('<h') || val.includes('#'))) {\n const headings = extractHeadingsFromRichText(val);\n for (const [tag, count] of Object.entries(headings)) {\n if (count > 0) {\n richTextCounts[tag] = (richTextCounts[tag] || 0) + count;\n }\n }\n } else if (Array.isArray(val) && val.length > 0 && typeof val[0] === 'object' && val[0]?.type) {\n // Strapi Blocks array\n const headings = extractHeadingsFromRichText(val);\n for (const [tag, count] of Object.entries(headings)) {\n if (count > 0) {\n richTextCounts[tag] = (richTextCounts[tag] || 0) + count;\n }\n }\n continue;\n }\n\n if (typeof val === 'object' && val !== null) {\n scanDataTree(val, newPath);\n }\n }\n }\n\n // If updating an existing document, merge incoming data with existing document\n // state so cross-component dynamic zone quotas are evaluated across the full tree\n let dataToScan = data;\n if (context.action === 'update' && (params?.documentId || params?.where?.documentId)) {\n const docId = params?.documentId || params?.where?.documentId;\n if (context.uid && docId) {\n try {\n const existing = await strapi.db?.query?.(context.uid)?.findOne?.({\n where: { documentId: docId },\n populate: true,\n });\n if (existing) {\n dataToScan = { ...existing, ...data };\n }\n } catch {\n // If lookup fails, scan incoming payload\n }\n }\n }\n\n scanDataTree(dataToScan);\n\n // Validate collected counts against active quotas\n for (const rule of effectiveRules) {\n const ruleCounts = structuredCounts[rule.id] || {};\n\n for (const [quotaKey, maxAllowed] of Object.entries(rule.quotas || {})) {\n const lowerVal = quotaKey.toLowerCase().trim();\n const structCount = ruleCounts[lowerVal] || 0;\n const rtCount = rule.includeRichTextHtml ? (richTextCounts[lowerVal] || 0) : 0;\n const totalFound = structCount + rtCount;\n\n if (totalFound > (maxAllowed as number)) {\n let detailMsg = `Option \"${quotaKey.toUpperCase()}\" cannot appear more than ${maxAllowed} time(s) across this entry.`;\n if (rtCount > 0 && structCount > 0) {\n detailMsg += ` Found ${totalFound} occurrences combined: ${structCount} in structured component ('${rule.targetField}') and ${rtCount} in rich text HTML / Markdown.`;\n } else if (rtCount > 0) {\n detailMsg += ` Found ${totalFound} in rich text HTML / Markdown content.`;\n } else {\n detailMsg += ` Found ${totalFound} in structured field '${rule.targetField}'.`;\n }\n throw createValidationError(rule.name, detailMsg, rule.targetField);\n }\n }\n }\n }\n }\n\n const result = await next();\n return result;\n });\n\n // Register universal Content History fallback middleware so Content History\n // operates reliably across all Strapi tiers (Community Edition and Enterprise)\n strapi.server.use(async (ctx: any, next: any) => {\n if (!ctx.path.startsWith('/content-manager/history-versions')) {\n await next();\n return;\n }\n\n await next();\n\n if (ctx.status === 404 || ctx.status === 405) {\n if (ctx.method === 'GET' && ctx.path === '/content-manager/history-versions') {\n const { contentType, documentId, locale, page = 1, pageSize = 20 } = ctx.query;\n if (!contentType) return;\n const historyQuery = strapi.db?.query?.('plugin::content-manager.history-version');\n if (!historyQuery) return;\n\n const pageNum = Math.max(1, parseInt(page, 10) || 1);\n const limit = Math.min(100, Math.max(1, parseInt(pageSize, 10) || 20));\n\n const whereClause: any = {\n contentType,\n ...(documentId ? { relatedDocumentId: documentId } : {}),\n ...(locale ? { locale } : {}),\n };\n\n const [results, total] = await Promise.all([\n historyQuery.findMany({\n where: whereClause,\n populate: ['createdBy'],\n orderBy: { createdAt: 'desc' },\n limit,\n offset: (pageNum - 1) * limit,\n }),\n historyQuery.count({ where: whereClause }),\n ]);\n\n const sanitizedResults = (results || []).map((ver: any) => ({\n ...ver,\n createdBy: ver.createdBy\n ? {\n id: ver.createdBy.id,\n firstname: ver.createdBy.firstname,\n lastname: ver.createdBy.lastname,\n username: ver.createdBy.username,\n email: ver.createdBy.email,\n }\n : undefined,\n meta: {\n unknownAttributes: { added: {}, removed: {} },\n },\n }));\n\n ctx.status = 200;\n ctx.body = {\n data: sanitizedResults,\n meta: {\n pagination: {\n page: pageNum,\n pageSize: limit,\n pageCount: Math.ceil(total / limit) || 1,\n total,\n },\n },\n };\n } else if (ctx.method === 'PUT' && ctx.path.endsWith('/restore')) {\n const match = ctx.path.match(/\\/content-manager\\/history-versions\\/([^/]+)\\/restore/);\n const versionId = match?.[1];\n if (!versionId) return;\n\n const historyQuery = strapi.db?.query?.('plugin::content-manager.history-version');\n const version = await historyQuery?.findOne?.({ where: { id: versionId } });\n if (!version) {\n ctx.status = 404;\n ctx.body = { error: 'Version not found' };\n return;\n }\n\n const restored = await strapi.documents(version.contentType).update({\n documentId: version.relatedDocumentId,\n locale: version.locale || undefined,\n data: version.data,\n });\n\n await recordContentHistoryVersion(strapi, {\n uid: version.contentType,\n documentId: version.relatedDocumentId,\n statusOverride: version.status || 'published',\n });\n\n ctx.status = 200;\n ctx.body = {\n data: {\n documentId: restored?.documentId || version.relatedDocumentId,\n },\n };\n }\n }\n });\n\n // Ensure database performance and concurrency resiliency for Content History\n try {\n const knex = strapi.db?.connection;\n if (knex) {\n // Optimize SQLite busy timeout to eliminate lock contention\n if (knex.client?.config?.client === 'sqlite3' || knex.client?.dialect === 'sqlite3') {\n knex.raw('PRAGMA busy_timeout = 10000;').catch(() => {});\n }\n\n // Ensure index exists on strapi_history_versions for high-speed queries\n knex.schema.hasTable('strapi_history_versions').then((hasTable: boolean) => {\n if (hasTable) {\n knex.raw(`\n CREATE INDEX IF NOT EXISTS idx_history_versions_lookup \n ON strapi_history_versions (content_type, related_document_id, created_at)\n `).catch(() => {});\n }\n }).catch(() => {});\n }\n } catch {}\n },\n routes,\n contentTypes,\n controllers: {\n bulkUpdater: bulkUpdaterController,\n audit: auditController,\n validationRules: validationRulesController,\n csv: csvController,\n },\n services: {\n bulkUpdater: bulkUpdaterService,\n audit: auditService,\n validationRules: validationRulesService,\n csv: csvService,\n contentHistory: contentHistoryService,\n },\n};\n"],"names":["csvService","buildDeepPopulate","currentVal","newValue","parsed","crypto","hasChange","auditService","ct","record","diffs","revertedCount","rollbackDetails","index","targetField","validationRulesService","errors"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../server/src/routes/index.ts","../../server/src/content-types/audit-log.ts","../../server/src/content-types/index.ts","../../server/src/controllers/bulk-updater.ts","../../server/src/controllers/audit.ts","../../server/src/controllers/validation-rules.ts","../../server/src/controllers/csv.ts","../../server/src/services/content-history.ts","../../server/src/services/bulk-updater.ts","../../server/src/services/audit.ts","../../server/src/services/validation-rules.ts","../../server/src/services/csv.ts","../../server/src/index.ts"],"sourcesContent":["export default {\n admin: {\n type: 'admin',\n routes: [\n {\n method: 'GET',\n path: '/models',\n handler: 'bulkUpdater.getModels',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/collections/:uid/entries',\n handler: 'bulkUpdater.getCollectionEntries',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/relation-options',\n handler: 'bulkUpdater.getRelationOptions',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/batch-update',\n handler: 'bulkUpdater.batchUpdate',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/batch-publish',\n handler: 'bulkUpdater.batchPublish',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/preview',\n handler: 'bulkUpdater.previewBatch',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/pending-batches',\n handler: 'bulkUpdater.getPendingBatches',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/batches/:batchId/approve',\n handler: 'bulkUpdater.approveBatch',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/batches/:batchId/reject',\n handler: 'bulkUpdater.rejectBatch',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/batches/:batchId/execute-now',\n handler: 'bulkUpdater.executeNow',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/batches/recent',\n handler: 'bulkUpdater.getRecentBatches',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/batches/:batchId/status',\n handler: 'bulkUpdater.getBatchStatus',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/batches/:batchId/report',\n handler: 'bulkUpdater.getBatchReport',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/batches/:batchId/diffs',\n handler: 'bulkUpdater.getPendingBatchDiffs',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/batches/:batchId/diffs/export',\n handler: 'bulkUpdater.exportPendingBatchDiffs',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/audit/history',\n handler: 'audit.getHistory',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/audit/:batchId/rollback',\n handler: 'audit.rollback',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/validation-rules',\n handler: 'validationRules.getRules',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/validation-rules',\n handler: 'validationRules.saveRule',\n config: {\n policies: [],\n },\n },\n {\n method: 'DELETE',\n path: '/validation-rules/:id',\n handler: 'validationRules.deleteRule',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/validation-rules/:id/toggle',\n handler: 'validationRules.toggleRule',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/validation-rules/:id/scan',\n handler: 'validationRules.scanViolations',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/csv/template/:uid',\n handler: 'csv.getTemplate',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/csv/export/:uid',\n handler: 'csv.exportCollection',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/csv/export/:uid',\n handler: 'csv.exportCollection',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/csv/export-bulk',\n handler: 'csv.exportBulk',\n config: {\n policies: [],\n },\n },\n {\n method: 'GET',\n path: '/csv/export-violations/:ruleId',\n handler: 'csv.exportViolations',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/csv/import',\n handler: 'csv.importCsv',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/csv/import-chunk',\n handler: 'csv.importChunk',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/csv/validate-preflight',\n handler: 'csv.validatePreflight',\n config: {\n policies: [],\n },\n },\n {\n method: 'POST',\n path: '/csv/submit-batch',\n handler: 'csv.submitBatch',\n config: {\n policies: [],\n },\n },\n ],\n },\n};\n","export default {\n collectionName: 'bulk_updater_audit_logs',\n info: {\n singularName: 'audit-log',\n pluralName: 'audit-logs',\n displayName: 'Bulk Updater Audit Log',\n description: 'Internal audit trail for bulk attribute and relation updates',\n },\n options: {\n draftAndPublish: false,\n },\n pluginOptions: {\n 'content-manager': {\n visible: true,\n },\n 'content-type-builder': {\n visible: false,\n },\n },\n attributes: {\n batchId: {\n type: 'string',\n required: true,\n },\n attribute: {\n type: 'string',\n required: true,\n },\n value: {\n type: 'text',\n },\n userEmail: {\n type: 'string',\n },\n userName: {\n type: 'string',\n },\n updatedCount: {\n type: 'integer',\n default: 0,\n },\n skippedCount: {\n type: 'integer',\n default: 0,\n },\n totalTargets: {\n type: 'integer',\n default: 0,\n },\n diffs: {\n type: 'json',\n },\n isRolledBack: {\n type: 'boolean',\n default: false,\n },\n rolledBackAt: {\n type: 'datetime',\n },\n rolledBackBy: {\n type: 'string',\n },\n executedAt: {\n type: 'datetime',\n },\n },\n};\n","import auditLog from './audit-log';\n\nexport default {\n 'audit-log': {\n schema: auditLog,\n },\n};\n","import type { Core } from '@strapi/strapi';\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => ({\n async getModels(ctx: any) {\n try {\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const data = await service.getModels();\n\n if (data?.etag) {\n ctx.set('ETag', data.etag);\n ctx.set('Cache-Control', 'private, no-cache');\n }\n\n ctx.body = data;\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async getCollectionEntries(ctx: any) {\n try {\n const { uid } = ctx.params;\n const { page, pageSize, attribute, searchAttribute, filterOperator, filterQuery, search, sortField, sortOrder } = ctx.query;\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const data = await service.getCollectionEntries(uid, {\n page: page ? Number(page) : 1,\n pageSize: pageSize ? Number(pageSize) : 10,\n attribute: attribute ? String(attribute) : undefined,\n searchAttribute: searchAttribute ? String(searchAttribute) : undefined,\n filterOperator: filterOperator ? String(filterOperator) : undefined,\n filterQuery: filterQuery !== undefined ? String(filterQuery) : undefined,\n search: search ? String(search) : undefined,\n sortField: sortField ? String(sortField) : undefined,\n sortOrder: sortOrder === 'asc' ? 'asc' : 'desc',\n });\n\n if (data?.etag) {\n ctx.set('ETag', data.etag);\n ctx.set('Cache-Control', 'private, no-cache');\n }\n\n ctx.body = { success: true, ...data };\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async getRelationOptions(ctx: any) {\n try {\n const { targetUid } = ctx.query;\n if (!targetUid) {\n ctx.status = 400;\n ctx.body = { success: false, error: 'targetUid is required' };\n return;\n }\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const data = await service.getRelationOptions(String(targetUid));\n ctx.body = { success: true, ...data };\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async batchUpdate(ctx: any) {\n try {\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const currentUser = ctx.state.user;\n const result = await service.batchUpdate(ctx.request.body || {}, currentUser);\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 400;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async batchPublish(ctx: any) {\n try {\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const currentUser = ctx.state.user;\n const result = await service.batchPublish(ctx.request.body || {}, currentUser);\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 400;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async previewBatch(ctx: any) {\n try {\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const result = await service.previewBatch(ctx.request.body || {});\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 400;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async getPendingBatches(ctx: any) {\n try {\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const result = await service.getPendingBatches();\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async approveBatch(ctx: any) {\n try {\n const { batchId } = ctx.params;\n const { executeImmediately = true } = ctx.request.body || {};\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const currentUser = ctx.state.user;\n const result = await service.approveBatch(batchId, currentUser, { executeImmediately });\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 400;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async rejectBatch(ctx: any) {\n try {\n const { batchId } = ctx.params;\n const { reason } = ctx.request.body || {};\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const currentUser = ctx.state.user;\n const result = await service.rejectBatch(batchId, currentUser, reason);\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 400;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async executeNow(ctx: any) {\n try {\n const { batchId } = ctx.params;\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const currentUser = ctx.state.user;\n const result = await service.executeNow(batchId, currentUser);\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 400;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async getBatchStatus(ctx: any) {\n try {\n const { batchId } = ctx.params;\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const result = await service.getBatchStatus(batchId);\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 404;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async getBatchReport(ctx: any) {\n try {\n const { batchId } = ctx.params;\n const { format = 'csv' } = ctx.query;\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const result = await service.getBatchReport(batchId, format);\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async getPendingBatchDiffs(ctx: any) {\n try {\n const { batchId } = ctx.params;\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const result = await service.getPendingBatchDiffs(batchId);\n ctx.body = result;\n } catch (err: any) {\n ctx.status = err.message?.includes('not found') ? 404 : 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async exportPendingBatchDiffs(ctx: any) {\n try {\n const { batchId } = ctx.params;\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const result = await service.getPendingBatchDiffsCsv(batchId);\n ctx.body = result;\n } catch (err: any) {\n ctx.status = err.message?.includes('not found') ? 404 : 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async getRecentBatches(ctx: any) {\n try {\n const service = strapi.plugin('bulk-updater').service('bulkUpdater');\n const result = await service.getRecentBatches();\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n});\n","import type { Core } from '@strapi/strapi';\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => ({\n async getHistory(ctx: any) {\n try {\n const service = strapi.plugin('bulk-updater').service('audit');\n const data = await service.getHistory();\n ctx.body = data;\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async rollback(ctx: any) {\n try {\n const { batchId } = ctx.params;\n const service = strapi.plugin('bulk-updater').service('audit');\n const currentUser = ctx.state.user;\n const result = await service.rollbackBatch(batchId, currentUser);\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 400;\n ctx.body = { success: false, error: err.message };\n }\n },\n});\n","import type { Core } from '@strapi/strapi';\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => ({\n async getRules(ctx: any) {\n try {\n const rules = await strapi.plugin('bulk-updater').service('validationRules').getRules();\n ctx.body = {\n success: true,\n rules,\n };\n } catch (err: any) {\n ctx.throw(500, err.message);\n }\n },\n\n async saveRule(ctx: any) {\n try {\n const { rule } = ctx.request.body || {};\n if (!rule) {\n return ctx.badRequest('Rule payload is required');\n }\n const saved = await strapi.plugin('bulk-updater').service('validationRules').saveRule(rule);\n ctx.body = {\n success: true,\n rule: saved,\n };\n } catch (err: any) {\n ctx.throw(500, err.message);\n }\n },\n\n async deleteRule(ctx: any) {\n try {\n const { id } = ctx.params;\n if (!id) {\n return ctx.badRequest('Rule ID is required');\n }\n await strapi.plugin('bulk-updater').service('validationRules').deleteRule(id);\n ctx.body = {\n success: true,\n id,\n };\n } catch (err: any) {\n ctx.throw(500, err.message);\n }\n },\n\n async toggleRule(ctx: any) {\n try {\n const { id } = ctx.params;\n const { enabled } = ctx.request.body || {};\n const updated = await strapi.plugin('bulk-updater').service('validationRules').toggleRule(id, enabled);\n if (!updated) {\n return ctx.notFound('Rule not found');\n }\n ctx.body = {\n success: true,\n rule: updated,\n };\n } catch (err: any) {\n ctx.throw(500, err.message);\n }\n },\n\n async scanViolations(ctx: any) {\n try {\n const { id } = ctx.params;\n if (!id) {\n return ctx.badRequest('Rule ID is required');\n }\n const report = await strapi.plugin('bulk-updater').service('validationRules').scanViolations(id);\n ctx.body = {\n success: true,\n ...report,\n };\n } catch (err: any) {\n ctx.throw(500, err.message);\n }\n },\n});\n","import type { Core } from '@strapi/strapi';\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => ({\n async getTemplate(ctx: any) {\n try {\n const { uid } = ctx.params;\n const csvService = strapi.plugin('bulk-updater').service('csv');\n const result = await csvService.getTemplateCsv(uid);\n ctx.body = {\n success: true,\n filename: result.filename,\n csvContent: result.csvContent,\n headers: result.headers,\n };\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async exportCollection(ctx: any) {\n try {\n const { uid } = ctx.params;\n const { search, attribute, filterOperator, filterQuery, limit, documentIds } = {\n ...ctx.query,\n ...(ctx.request?.body || {}),\n };\n const csvService = strapi.plugin('bulk-updater').service('csv');\n\n let parsedDocIds: string[] | undefined;\n if (documentIds) {\n parsedDocIds = Array.isArray(documentIds)\n ? documentIds\n : String(documentIds)\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n }\n\n const result = await csvService.exportCollectionCsv(uid, {\n search: search ? String(search) : undefined,\n attribute: attribute ? String(attribute) : undefined,\n filterOperator: filterOperator ? String(filterOperator) : undefined,\n filterQuery: filterQuery !== undefined ? String(filterQuery) : undefined,\n limit: limit ? Number(limit) : undefined,\n documentIds: parsedDocIds,\n });\n\n ctx.body = {\n success: true,\n filename: result.filename,\n csvContent: result.csvContent,\n count: result.count,\n fields: result.fields,\n };\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async exportBulk(ctx: any) {\n try {\n const { selectedEntries } = ctx.request.body || {};\n const csvService = strapi.plugin('bulk-updater').service('csv');\n const result = await csvService.exportBulkCsv(selectedEntries);\n\n ctx.body = {\n success: true,\n filename: result.filename,\n csvContent: result.csvContent,\n count: result.count,\n isMultiCollection: result.isMultiCollection,\n };\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async exportViolations(ctx: any) {\n try {\n const { ruleId } = ctx.params;\n const csvService = strapi.plugin('bulk-updater').service('csv');\n const result = await csvService.exportViolationsCsv(ruleId);\n\n ctx.body = {\n success: true,\n filename: result.filename,\n csvContent: result.csvContent,\n count: result.count,\n ruleName: result.ruleName,\n };\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async importCsv(ctx: any) {\n try {\n const { uid, csvText, mode, publish, publishStrategy, unreviewedConsent } = ctx.request.body;\n if (!uid) {\n ctx.status = 400;\n ctx.body = { success: false, error: 'Target collection UID is required.' };\n return;\n }\n if (!csvText || typeof csvText !== 'string') {\n ctx.status = 400;\n ctx.body = { success: false, error: 'CSV content is required.' };\n return;\n }\n\n const csvService = strapi.plugin('bulk-updater').service('csv');\n const result = await csvService.importCsv(uid, csvText, {\n mode: mode === 'update' ? 'update' : mode === 'create_or_override' ? 'create_or_override' : 'auto',\n publish: publish !== false,\n publishStrategy: publishStrategy === 'all' ? 'all' : 'safe',\n unreviewedConsent: Boolean(unreviewedConsent),\n user: ctx.state.user,\n });\n\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async importChunk(ctx: any) {\n try {\n const { uid, rows, batchId, isFirstChunk, isLastChunk, startRowNumber, mode, publish, publishStrategy, unreviewedConsent } = ctx.request.body;\n if (!uid) {\n ctx.status = 400;\n ctx.body = { success: false, error: 'Target collection UID is required.' };\n return;\n }\n if (!Array.isArray(rows)) {\n ctx.status = 400;\n ctx.body = { success: false, error: 'Rows array is required.' };\n return;\n }\n\n const csvService = strapi.plugin('bulk-updater').service('csv');\n const result = await csvService.importChunk(uid, rows, {\n batchId: batchId ? String(batchId) : undefined,\n isFirstChunk: Boolean(isFirstChunk),\n isLastChunk: Boolean(isLastChunk),\n startRowNumber: typeof startRowNumber === 'number' ? startRowNumber : undefined,\n mode: mode === 'update' ? 'update' : mode === 'create_or_override' ? 'create_or_override' : 'auto',\n publish: publish !== false,\n publishStrategy: publishStrategy === 'all' ? 'all' : 'safe',\n unreviewedConsent: Boolean(unreviewedConsent),\n user: ctx.state.user,\n });\n\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async validatePreflight(ctx: any) {\n try {\n const { uid, rows, mode } = ctx.request.body;\n if (!uid) {\n ctx.status = 400;\n ctx.body = { success: false, error: 'Target collection UID is required.' };\n return;\n }\n if (!Array.isArray(rows)) {\n ctx.status = 400;\n ctx.body = { success: false, error: 'Rows array is required.' };\n return;\n }\n\n const csvService = strapi.plugin('bulk-updater').service('csv');\n const result = await csvService.validatePreflight(uid, rows, {\n mode: mode === 'update' ? 'update' : mode === 'create_or_override' ? 'create_or_override' : 'auto',\n });\n\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n\n async submitBatch(ctx: any) {\n try {\n const { uid, rows, executionMode, makerNotes, forceImmediate, mode, publish, publishStrategy, unreviewedConsent, unreviewedCount } = ctx.request.body;\n if (!uid) {\n ctx.status = 400;\n ctx.body = { success: false, error: 'Target collection UID is required.' };\n return;\n }\n if (!Array.isArray(rows)) {\n ctx.status = 400;\n ctx.body = { success: false, error: 'Rows array is required.' };\n return;\n }\n\n const csvService = strapi.plugin('bulk-updater').service('csv');\n const result = await csvService.submitBatch(uid, rows, {\n executionMode,\n makerNotes,\n forceImmediate: Boolean(forceImmediate),\n mode: mode === 'update' ? 'update' : mode === 'create_or_override' ? 'create_or_override' : 'auto',\n publish: publish !== false,\n publishStrategy: publishStrategy === 'all' ? 'all' : 'safe',\n unreviewedConsent: Boolean(unreviewedConsent),\n unreviewedCount: typeof unreviewedCount === 'number' ? unreviewedCount : 0,\n user: ctx.state.user,\n });\n\n ctx.body = result;\n } catch (err: any) {\n ctx.status = 500;\n ctx.body = { success: false, error: err.message };\n }\n },\n});\n","import type { Core } from '@strapi/strapi';\n\nconst FIELDS_TO_IGNORE = [\n 'createdAt',\n 'updatedAt',\n 'publishedAt',\n 'createdBy',\n 'updatedBy',\n 'strapi_stage',\n 'strapi_assignee',\n];\n\n/**\n * Builds a recursive Strapi 5 populate tree for deep nested components, relations, and media\n */\nfunction buildHistoryPopulate(\n attributes: Record<string, any>,\n allComponents: Record<string, any>,\n depth = 0\n): Record<string, any> | undefined {\n if (depth > 5) return undefined;\n const populate: Record<string, any> = {};\n\n for (const [key, def] of Object.entries(attributes || {}) as any[]) {\n if (def.type === 'component' && def.component) {\n const comp = allComponents[def.component];\n if (comp?.attributes) {\n const subPopulate = buildHistoryPopulate(comp.attributes, allComponents, depth + 1);\n if (subPopulate && Object.keys(subPopulate).length > 0) {\n populate[key] = {\n populate: subPopulate,\n };\n } else {\n populate[key] = true;\n }\n } else {\n populate[key] = true;\n }\n } else if (def.type === 'dynamiczone') {\n populate[key] = true;\n } else if (def.type === 'relation' || def.type === 'media') {\n populate[key] = true;\n }\n }\n\n return Object.keys(populate).length > 0 ? populate : undefined;\n}\n\nlet cachedAdminUserId: number | null = null;\n\nexport interface ContentHistoryRecordOptions {\n uid: string;\n documentId: string;\n userId?: number | string | null;\n statusOverride?: 'draft' | 'published' | 'modified';\n}\n\n/**\n * Records a Content History version in Strapi's plugin::content-manager.history-version\n * so that any bulk-updated, bulk-published, rolled-back, or CSV-imported record accurately\n * reflects in Strapi's Content History timeline in Content Manager.\n */\nexport async function recordContentHistoryVersion(\n strapi: any,\n options: ContentHistoryRecordOptions\n): Promise<void> {\n const { uid, documentId, userId, statusOverride } = options;\n\n if (!uid || !uid.startsWith('api::') || !documentId) {\n return;\n }\n\n try {\n const historyQuery = strapi.db?.query?.('plugin::content-manager.history-version');\n if (!historyQuery) {\n return;\n }\n\n const model = strapi.getModel?.(uid);\n if (!model) {\n return;\n }\n\n // 1. Fetch updated document state directly via db.query to avoid document service middleware recursion\n let entry: any = null;\n try {\n entry = await strapi.db.query(uid).findOne({\n where: { documentId },\n populate: true,\n });\n } catch {\n try {\n const populateOption = buildHistoryPopulate(model.attributes || {}, strapi.components || {});\n entry = await strapi.documents(uid as any).findOne({\n documentId,\n ...(populateOption ? { populate: populateOption } : {}),\n });\n } catch {\n entry = null;\n }\n }\n\n if (!entry) {\n return;\n }\n\n // 2. Prepare sanitized schema for diff inspection and restore\n const attributesSchema = model.attributes || {};\n const sanitizedSchema = Object.fromEntries(\n Object.entries(attributesSchema).filter(([k]) => !FIELDS_TO_IGNORE.includes(k))\n );\n\n // 3. Prepare sanitized data snapshot\n const sanitizedData = Object.fromEntries(\n Object.entries(entry).filter(([k]) => !FIELDS_TO_IGNORE.includes(k) && k !== 'id')\n );\n\n // 4. Calculate version status\n let status: 'draft' | 'published' | 'modified' = statusOverride || 'published';\n if (!statusOverride) {\n const hasDraftAndPublish = Boolean(model.options?.draftAndPublish);\n if (hasDraftAndPublish) {\n try {\n const docMetaService = strapi.plugin('content-manager')?.service('document-metadata');\n if (docMetaService) {\n const meta = await docMetaService.getMetadata(uid, entry);\n status = docMetaService.getStatus(entry, meta.availableStatus);\n } else {\n status = entry.publishedAt ? 'published' : 'draft';\n }\n } catch {\n status = entry.publishedAt ? 'published' : 'draft';\n }\n } else {\n status = 'published';\n }\n }\n\n // 5. Resolve creator ID\n let authorId = userId;\n if (!authorId) {\n authorId = strapi.requestContext?.get?.()?.state?.user?.id || null;\n }\n let numericUserId = authorId ? Number(authorId) : null;\n if (!numericUserId || isNaN(numericUserId)) {\n if (cachedAdminUserId) {\n numericUserId = cachedAdminUserId;\n } else {\n try {\n const firstAdmin = await strapi.db?.query?.('admin::user')?.findOne?.({ select: ['id'] });\n if (firstAdmin?.id) {\n cachedAdminUserId = Number(firstAdmin.id);\n numericUserId = cachedAdminUserId;\n }\n } catch {}\n }\n }\n\n // 6. Insert record into plugin::content-manager.history-version (strapi_history_versions)\n await historyQuery.create({\n data: {\n contentType: uid,\n relatedDocumentId: documentId,\n locale: entry.locale || null,\n status,\n data: sanitizedData,\n schema: sanitizedSchema,\n createdAt: new Date(),\n ...(numericUserId && !isNaN(numericUserId) ? { createdBy: numericUserId } : {}),\n },\n });\n } catch (err: any) {\n strapi.log?.warn?.(`[bulk-updater] Non-blocking Content History notice for ${uid}/${documentId}: ${err?.message}`);\n }\n}\n\n/**\n * Bulk version recorder: processes an array of document IDs in parallel batches\n */\nexport async function recordContentHistoryVersionsBatch(\n strapi: any,\n items: ContentHistoryRecordOptions[]\n): Promise<void> {\n if (!items || items.length === 0) return;\n const BATCH_SIZE = 10;\n for (let i = 0; i < items.length; i += BATCH_SIZE) {\n const slice = items.slice(i, i + BATCH_SIZE);\n await Promise.all(slice.map((item) => recordContentHistoryVersion(strapi, item)));\n }\n}\n\nexport default {\n recordContentHistoryVersion,\n recordContentHistoryVersionsBatch,\n};\n","import type { Core } from '@strapi/strapi';\nimport crypto from 'crypto';\nimport { recordContentHistoryVersion } from './content-history';\n\n// In-process memory caches (scoped to pod)\ninterface CacheEntry {\n signature: string;\n data: any;\n timestamp: number;\n}\n\nconst queryCache = new Map<string, CacheEntry>();\nconst modelsCache = new Map<string, { signature: string; totalCount: number; entries: any[] }>();\nconst MAX_QUERY_CACHE_SIZE = 500;\nconst CACHE_TTL_MS = 60 * 1000; // 60-second TTL fallback\n\nexport interface RelationMeta {\n isRelation: boolean;\n relationType: string;\n targetUid: string;\n targetDisplayName: string;\n isMulti: boolean;\n}\n\nexport interface AttributeMeta {\n depth: number;\n type: string;\n component?: string;\n isRelation?: boolean;\n}\n\nlet staticSchemaCache: {\n attributes: string[];\n attributesMeta: Record<string, AttributeMeta>;\n targetUids: string[];\n metaByUid: Record<\n string,\n {\n uid: string;\n kind: string;\n isSingleType: boolean;\n singularName: string;\n pluralName: string;\n displayName: string;\n attributes: string[];\n attributesMeta: Record<string, AttributeMeta>;\n relations: Record<string, RelationMeta>;\n }\n >;\n relationsMeta: Record<string, RelationMeta>;\n} | null = null;\n\n/**\n * Ensures consistent two-way mapping for timestamp aliases (updated_at <-> updatedAt,\n * created_at <-> createdAt, published_at <-> publishedAt) so columns in any collection\n * (such as st-feature with updated_at) are properly reflected regardless of source.\n */\nexport function formatEntryRecord(entry: any): any {\n if (!entry || typeof entry !== 'object') return entry;\n const formatted: any = {\n id: entry.id,\n documentId: entry.documentId,\n ...entry,\n };\n if (entry.updatedAt !== undefined && formatted.updated_at === undefined) {\n formatted.updated_at = entry.updatedAt;\n }\n if (entry.updated_at !== undefined && formatted.updatedAt === undefined) {\n formatted.updatedAt = entry.updated_at;\n }\n if (entry.createdAt !== undefined && formatted.created_at === undefined) {\n formatted.created_at = entry.createdAt;\n }\n if (entry.created_at !== undefined && formatted.createdAt === undefined) {\n formatted.createdAt = entry.created_at;\n }\n if (entry.publishedAt !== undefined && formatted.published_at === undefined) {\n formatted.published_at = entry.publishedAt;\n }\n if (entry.published_at !== undefined && formatted.publishedAt === undefined) {\n formatted.publishedAt = entry.published_at;\n }\n return formatted;\n}\n\n/**\n * Resolves a sort or filter field name against a content type schema,\n * checking system timestamps (updatedAt <-> updated_at, createdAt <-> created_at, publishedAt <-> published_at),\n * standard identifiers (id, documentId), and snake_case <-> camelCase attribute variants.\n */\nexport function resolveContentTypeField(contentType: any, field: string): string | null {\n if (!field) return null;\n const attrs = contentType?.attributes || {};\n if (attrs[field]) return field;\n\n // 1. System timestamp & identifier resolution\n if (field === 'updated_at' || field === 'updatedAt') {\n return attrs['updated_at'] ? 'updated_at' : 'updatedAt';\n }\n if (field === 'created_at' || field === 'createdAt') {\n return attrs['created_at'] ? 'created_at' : 'createdAt';\n }\n if (field === 'published_at' || field === 'publishedAt') {\n return attrs['published_at'] ? 'published_at' : 'publishedAt';\n }\n if (field === 'id' || field === 'documentId') {\n return field;\n }\n\n // 2. snake_case -> camelCase\n const camel = field.replace(/_([a-z0-9])/g, (_, l) => l.toUpperCase());\n if (attrs[camel]) return camel;\n\n // 3. camelCase -> snake_case\n const snake = field.replace(/([A-Z])/g, '_$1').toLowerCase();\n if (attrs[snake]) return snake;\n\n // 4. Case-insensitive / underscore-insensitive match across attributes\n const lower = field.toLowerCase().replace(/_/g, '');\n const matched = Object.keys(attrs).find(\n (k) => k.toLowerCase().replace(/_/g, '') === lower\n );\n if (matched) return matched;\n\n return null;\n}\n\n/**\n * Builds a recursive Strapi 5 populate tree for deep nested components, relations, and media\n */\nexport function buildDeepPopulate(\n attributes: Record<string, any>,\n allComponents: Record<string, any>,\n depth = 0\n): Record<string, any> | undefined {\n if (depth > 5) return undefined;\n const populate: Record<string, any> = {};\n\n for (const [key, def] of Object.entries(attributes || {}) as any[]) {\n if (def.type === 'component' && def.component) {\n const comp = allComponents[def.component];\n if (comp?.attributes) {\n const subPopulate = buildDeepPopulate(comp.attributes, allComponents, depth + 1);\n if (subPopulate && Object.keys(subPopulate).length > 0) {\n populate[key] = {\n populate: subPopulate,\n };\n } else {\n populate[key] = true;\n }\n } else {\n populate[key] = true;\n }\n } else if (def.type === 'dynamiczone') {\n populate[key] = {\n populate: '*',\n };\n } else if (def.type === 'relation' || def.type === 'media') {\n populate[key] = true;\n }\n }\n\n return Object.keys(populate).length > 0 ? populate : undefined;\n}\n\n/**\n * Recursively discovers component fields down to a specified maxDepth (up to 5 levels)\n */\nexport function discoverComponentAttributes(\n strapi: any,\n compUid: string,\n prefix: string,\n currentDepth: number,\n maxDepth: number,\n systemFields: string[],\n allContentTypes: Record<string, any>,\n relationsByAttr: Record<string, RelationMeta>,\n allRelationsMeta: Record<string, RelationMeta>,\n attributesMeta: Record<string, AttributeMeta>\n): string[] {\n if (currentDepth > maxDepth || !compUid) return [];\n const compSchema = strapi.components[compUid];\n if (!compSchema?.attributes) return [];\n\n const discoveredAttrs: string[] = [];\n\n for (const [subKey, subAttr] of Object.entries(compSchema.attributes) as any[]) {\n if (systemFields.includes(subKey)) continue;\n const fullPath = prefix ? `${prefix}.${subKey}` : subKey;\n\n if (subAttr.type === 'dynamiczone') {\n const dzComps = Array.isArray(subAttr.components) ? subAttr.components : [];\n for (const dzCompUid of dzComps) {\n const deeper = discoverComponentAttributes(\n strapi,\n dzCompUid,\n fullPath,\n currentDepth + 1,\n maxDepth,\n systemFields,\n allContentTypes,\n relationsByAttr,\n allRelationsMeta,\n attributesMeta\n );\n discoveredAttrs.push(...deeper);\n }\n continue;\n }\n\n if (subAttr.type === 'component') {\n if (subAttr.component) {\n const deeper = discoverComponentAttributes(\n strapi,\n subAttr.component,\n fullPath,\n currentDepth + 1,\n maxDepth,\n systemFields,\n allContentTypes,\n relationsByAttr,\n allRelationsMeta,\n attributesMeta\n );\n discoveredAttrs.push(...deeper);\n }\n } else if (subAttr.type === 'relation') {\n const targetUid = subAttr.target;\n if (targetUid && allContentTypes[targetUid]) {\n const targetInfo = allContentTypes[targetUid]?.info;\n const isMulti = subAttr.relation === 'oneToMany' || subAttr.relation === 'manyToMany';\n const relMeta: RelationMeta = {\n isRelation: true,\n relationType: subAttr.relation,\n targetUid,\n targetDisplayName: targetInfo?.displayName || targetUid,\n isMulti,\n };\n relationsByAttr[fullPath] = relMeta;\n allRelationsMeta[fullPath] = relMeta;\n attributesMeta[fullPath] = { depth: currentDepth, type: 'relation', component: compUid, isRelation: true };\n discoveredAttrs.push(fullPath);\n }\n } else {\n attributesMeta[fullPath] = { depth: currentDepth, type: subAttr.type, component: compUid };\n discoveredAttrs.push(fullPath);\n }\n }\n\n return Array.from(new Set(discoveredAttrs));\n}\n\n/**\n * Parses dynamic zone dot or bracket notation paths:\n * e.g. \"blocks.title\", \"blocks[shared.heading].title\", or \"blocks[0].title\"\n */\nexport function parseDynamicZonePath(path: string): {\n cleanPath: string;\n rootKey: string;\n subPath: string;\n targetComponentUid?: string;\n targetIndex?: number;\n} {\n if (!path) return { cleanPath: '', rootKey: '', subPath: '' };\n const bracketMatch = path.match(/^([^.[]+)\\[([^\\]]+)\\](?:\\.(.+))?$/);\n if (bracketMatch) {\n const rootKey = bracketMatch[1];\n const selector = bracketMatch[2].trim();\n const subPath = bracketMatch[3] || '';\n const cleanPath = subPath ? `${rootKey}.${subPath}` : rootKey;\n const numMatch = selector.match(/^#?(\\d+)/);\n if (numMatch) {\n return { cleanPath, rootKey, subPath, targetIndex: parseInt(numMatch[1], 10) };\n }\n return { cleanPath, rootKey, subPath, targetComponentUid: selector };\n }\n\n const parts = path.split('.');\n return {\n cleanPath: path,\n rootKey: parts[0] || '',\n subPath: parts.slice(1).join('.'),\n };\n}\n\n/**\n * Formats a component UID into a friendly readable label (e.g. \"shared.featured-section\" -> \"Featured Section\")\n */\nexport function formatComponentName(compUid?: string): string {\n if (!compUid) return 'Component';\n const name = compUid.includes('.') ? compUid.split('.')[1] : compUid;\n return name\n .split(/[-_]/)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(' ');\n}\n\nexport interface DynamicZoneItemMatch {\n index: number;\n componentUid?: string;\n componentName?: string;\n value: any;\n path: string;\n}\n\n/**\n * Extracts all matching instances of a nested property across dynamic zone components or repeatable arrays.\n */\nexport function getAllNestedValues(obj: any, path: string): DynamicZoneItemMatch[] {\n if (!obj || !path) return [];\n const parsed = parseDynamicZonePath(path);\n const parts = parsed.cleanPath.split('.');\n const [head, ...tail] = parts;\n\n const rootTarget = obj[head];\n\n // If rootTarget is an Array (Dynamic Zone or Repeatable Component)\n if (Array.isArray(rootTarget)) {\n const results: DynamicZoneItemMatch[] = [];\n rootTarget.forEach((item, idx) => {\n if (!item || typeof item !== 'object') return;\n if (parsed.targetIndex !== undefined && idx !== parsed.targetIndex) return;\n if (parsed.targetComponentUid && item.__component !== parsed.targetComponentUid) return;\n\n const compSchema = (global as any).strapi?.components?.[item.__component];\n const fieldInSchema = tail.length > 0 && compSchema?.attributes\n ? tail[0] in compSchema.attributes\n : false;\n\n const subVal = tail.length > 0 ? getDeepProperty(item, tail.join('.')) : item;\n if (subVal !== undefined || fieldInSchema) {\n results.push({\n index: idx,\n componentUid: item.__component,\n componentName: formatComponentName(item.__component),\n value: subVal !== undefined ? subVal : null,\n path: `${head}[#${idx}${item.__component ? ` ${formatComponentName(item.__component)}` : ''}].${tail.join('.')}`,\n });\n }\n });\n return results;\n }\n\n // Not an array, standard object resolution\n const singleVal = getDeepProperty(obj, parsed.cleanPath);\n if (singleVal !== undefined) {\n return [\n {\n index: 0,\n value: singleVal,\n path: parsed.cleanPath,\n },\n ];\n }\n\n return [];\n}\n\n/**\n * Validates whether an attribute corresponds to a valid deep component hierarchy\n */\nexport function isDeepComponentField(contentType: any, allComponents: Record<string, any>, attribute: string): boolean {\n if (!attribute || (!attribute.includes('.') && !attribute.includes('['))) return false;\n const parsed = parseDynamicZonePath(attribute);\n const parts = parsed.cleanPath.split('.');\n\n function checkPath(currentSchema: any, pathParts: string[]): boolean {\n if (pathParts.length === 0) return true;\n if (!currentSchema || !currentSchema.attributes) return false;\n const [head, ...tail] = pathParts;\n const attrDef = currentSchema.attributes[head];\n if (!attrDef) return false;\n\n if (tail.length === 0) {\n return true;\n }\n\n if (attrDef.type === 'component' && attrDef.component) {\n const comp = allComponents[attrDef.component];\n return checkPath(comp, tail);\n }\n\n if (attrDef.type === 'dynamiczone') {\n const compUids = Array.isArray(attrDef.components) ? attrDef.components : [];\n if (parsed.targetComponentUid) {\n const comp = allComponents[parsed.targetComponentUid];\n return comp ? checkPath(comp, tail) : false;\n }\n return compUids.some((compUid: string) => {\n const comp = allComponents[compUid];\n return checkPath(comp, tail);\n });\n }\n\n return false;\n }\n\n return checkPath(contentType, parts);\n}\n\n/**\n * Retrieves the schema definition of a leaf attribute from a deep dot-notation or bracket path\n */\nexport function getLeafAttributeSchema(contentType: any, allComponents: Record<string, any>, attribute: string): any {\n if (!attribute) return null;\n const parsed = parseDynamicZonePath(attribute);\n if (!parsed.cleanPath.includes('.')) return contentType?.attributes?.[parsed.cleanPath] || null;\n const parts = parsed.cleanPath.split('.');\n\n function resolveLeaf(currentSchema: any, pathParts: string[]): any {\n if (!currentSchema || !currentSchema.attributes) return null;\n const [head, ...tail] = pathParts;\n const attrDef = currentSchema.attributes[head];\n if (!attrDef) return null;\n\n if (tail.length === 0) {\n return attrDef;\n }\n\n if (attrDef.type === 'component' && attrDef.component) {\n return resolveLeaf(allComponents[attrDef.component], tail);\n }\n\n if (attrDef.type === 'dynamiczone') {\n const compUids = Array.isArray(attrDef.components) ? attrDef.components : [];\n if (parsed.targetComponentUid) {\n return resolveLeaf(allComponents[parsed.targetComponentUid], tail);\n }\n for (const compUid of compUids) {\n const found = resolveLeaf(allComponents[compUid], tail);\n if (found) return found;\n }\n }\n\n return null;\n }\n\n return resolveLeaf(contentType, parts);\n}\n\n/**\n * Immutably sets a nested property at an arbitrary depth while preserving all sibling properties.\n * Fully supports selective targeting of specific dynamic zone indices or component types.\n */\nexport function setDeepProperty(\n obj: any,\n pathParts: string[],\n value: any,\n options?: {\n targetIndexes?: number[];\n targetComponentUid?: string;\n }\n): any {\n if (pathParts.length === 0) return value;\n const [head, ...tail] = pathParts;\n\n // Case 1: If current obj is an Array (e.g. Dynamic Zone or Repeatable Component)\n if (Array.isArray(obj)) {\n // If head is a numeric index, update only that specific index\n if (/^\\d+$/.test(head)) {\n const idx = parseInt(head, 10);\n const copy = [...obj];\n copy[idx] = setDeepProperty(copy[idx] || {}, tail, value, options);\n return copy;\n }\n\n // Otherwise, head is a property name inside the array items!\n // Update items according to options.targetIndexes / options.targetComponentUid\n return obj.map((item, idx) => {\n if (!item || typeof item !== 'object') return item;\n\n if (options?.targetIndexes && options.targetIndexes.length > 0) {\n if (!options.targetIndexes.includes(idx)) return item;\n }\n\n if (options?.targetComponentUid) {\n if (item.__component !== options.targetComponentUid) return item;\n }\n\n const compSchema = (global as any).strapi?.components?.[item.__component];\n const fieldExistsInSchema = compSchema?.attributes ? head in compSchema.attributes : true;\n\n if (head in item || fieldExistsInSchema || tail.length === 0) {\n return {\n ...item,\n [head]: setDeepProperty(item[head], tail, value, options),\n };\n }\n return item;\n });\n }\n\n // Case 2: obj is an Object\n const current = { ...(obj || {}) };\n if (tail.length === 0) {\n current[head] = value;\n } else {\n const subTarget = current[head];\n if (Array.isArray(subTarget)) {\n current[head] = setDeepProperty(subTarget, tail, value, options);\n } else {\n current[head] = setDeepProperty(subTarget || {}, tail, value, options);\n }\n }\n return current;\n}\n\n/**\n * Safely resolves a nested dot-notation property (e.g. \"a.b.c.d\" or bracket notation) across objects and dynamic zone arrays\n */\nexport function getDeepProperty(obj: any, path: string): any {\n if (!obj || !path) return undefined;\n const parsed = parseDynamicZonePath(path);\n const parts = parsed.cleanPath.split('.');\n\n function extract(current: any, remainingParts: string[]): any {\n if (current === undefined || current === null) return undefined;\n if (remainingParts.length === 0) return current;\n\n const [head, ...tail] = remainingParts;\n\n if (Array.isArray(current)) {\n if (/^\\d+$/.test(head)) {\n return extract(current[parseInt(head, 10)], tail);\n }\n for (let idx = 0; idx < current.length; idx++) {\n const item = current[idx];\n if (parsed.targetIndex !== undefined && idx !== parsed.targetIndex) continue;\n if (parsed.targetComponentUid && item?.__component !== parsed.targetComponentUid) continue;\n const found = extract(item?.[head], tail);\n if (found !== undefined && found !== null) return found;\n }\n return undefined;\n }\n\n return extract(current[head], tail);\n }\n\n return extract(obj, parts);\n}\n\n/**\n * Constructs a nested filter object for Strapi 5 Document queries (e.g. { a: { b: { c: condition } } })\n */\nexport function buildDeepFilter(pathParts: string[], condition: any): any {\n if (pathParts.length === 0) return condition;\n const [head, ...tail] = pathParts;\n return {\n [head]: buildDeepFilter(tail, condition),\n };\n}\n\nexport interface ExecutionWindowConfig {\n enabled: boolean;\n timeZone: string;\n businessHours: {\n start: string;\n end: string;\n };\n offPeakStartTime: string;\n autoQueueDuringBusinessHours: boolean;\n}\n\nexport function getSafeTimezone(timeZone?: string): string {\n if (!timeZone || typeof timeZone !== 'string') {\n return Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';\n }\n try {\n Intl.DateTimeFormat(undefined, { timeZone: timeZone.trim() });\n return timeZone.trim();\n } catch {\n return 'UTC';\n }\n}\n\nexport function getTimeInTimezone(timeZone: string, date: Date = new Date()): { hours: number; minutes: number; timeString: string } {\n const safeTz = getSafeTimezone(timeZone);\n const formatter = new Intl.DateTimeFormat('en-GB', {\n timeZone: safeTz,\n hour: '2-digit',\n minute: '2-digit',\n hourCycle: 'h23',\n });\n const timeString = formatter.format(date);\n const [h, m] = timeString.split(':').map(Number);\n return { hours: h, minutes: m, timeString };\n}\n\nexport function getExecutionWindowConfig(strapi: Core.Strapi): ExecutionWindowConfig {\n const pluginConfig = strapi.config.get('plugin::bulk-updater.executionWindow') as Partial<ExecutionWindowConfig> | undefined;\n const configuredTz = pluginConfig?.timeZone ||\n strapi.config.get('server.timeZone') ||\n Intl.DateTimeFormat().resolvedOptions().timeZone ||\n 'UTC';\n const timeZone = getSafeTimezone(configuredTz);\n\n return {\n enabled: pluginConfig?.enabled ?? true,\n timeZone,\n businessHours: {\n start: pluginConfig?.businessHours?.start || '09:00',\n end: pluginConfig?.businessHours?.end || '18:00',\n },\n offPeakStartTime: pluginConfig?.offPeakStartTime || '18:00',\n autoQueueDuringBusinessHours: pluginConfig?.autoQueueDuringBusinessHours ?? true,\n };\n}\n\nexport function checkBusinessHours(config: ExecutionWindowConfig, testDate?: Date) {\n const timeZone = getSafeTimezone(config.timeZone);\n const { hours, minutes, timeString } = getTimeInTimezone(timeZone, testDate || new Date());\n\n const currentMinutes = hours * 60 + minutes;\n const [startH, startM] = (config.businessHours.start || '09:00').split(':').map(Number);\n const [endH, endM] = (config.businessHours.end || '18:00').split(':').map(Number);\n const startMinutes = startH * 60 + startM;\n const endMinutes = endH * 60 + endM;\n\n const isBusinessHours = currentMinutes >= startMinutes && currentMinutes < endMinutes;\n\n return {\n isBusinessHours,\n currentServerTime: timeString,\n timeZone,\n businessHours: config.businessHours,\n offPeakStartTime: config.offPeakStartTime,\n policyMessage: isBusinessHours\n ? `Server policy restricts bulk updates during peak business hours (${config.businessHours.start} - ${config.businessHours.end} ${timeZone}). Current time: ${timeString} (${timeZone}). Updates will be queued for off-peak execution at ${config.offPeakStartTime} ${timeZone}.`\n : `Currently in off-peak execution window (outside ${config.businessHours.start} - ${config.businessHours.end} ${timeZone}). Current time: ${timeString} (${timeZone}). Direct execution is permitted.`,\n };\n}\n\nexport interface PendingBatch {\n id: string;\n createdAt: string;\n createdBy: { id?: string | number; email?: string; firstname?: string; lastname?: string; username?: string };\n payload: {\n action?: string;\n attribute: string;\n value: string;\n selectedEntries?: Array<{ uid: string; documentId: string; dynamicZoneIndexes?: number[]; targetComponentUid?: string }>;\n selectedCollections?: string[];\n isRegex?: boolean;\n regexPattern?: string;\n publishOnApproval?: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n unreviewedCount?: number;\n rows?: any[];\n uid?: string;\n options?: any;\n };\n summary: {\n attribute: string;\n value: string;\n totalTargets: number;\n collectionBreakdown: Record<string, number>;\n publishOnApproval?: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n unreviewedCount?: number;\n };\n status: 'pending_approval' | 'queued_offpeak' | 'approved' | 'rejected' | 'executed';\n executionMode: 'maker_checker' | 'queue_offpeak' | 'immediate';\n scheduledFor?: string;\n makerNotes?: string;\n approval?: {\n checkerUser?: { id?: string | number; email?: string; firstname?: string; lastname?: string; username?: string };\n decisionDate?: string;\n rejectionReason?: string;\n };\n executionResult?: any;\n}\n\nexport interface BatchJobState {\n id: string;\n createdAt: string;\n startedAt?: string;\n completedAt?: string;\n createdBy: { id?: string | number; email?: string; firstname?: string; lastname?: string; username?: string };\n status: 'pending_approval' | 'queued_offpeak' | 'processing' | 'successful' | 'partial_failure' | 'failed';\n executionMode: 'immediate' | 'maker_checker' | 'queue_offpeak';\n scheduledFor?: string;\n attribute: string;\n value: string;\n totalTargets: number;\n processedCount: number;\n updatedCount: number;\n skippedCount: number;\n failedCount: number;\n isLive: boolean;\n publishOnApproval: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n unreviewedCount?: number;\n policyMessage?: string;\n makerNotes?: string;\n results: Array<{\n uid: string;\n collectionName: string;\n documentId: string;\n label: string;\n attribute: string;\n oldValue: any;\n newValue: any;\n status: 'updated' | 'skipped' | 'error';\n message: string;\n isLive?: boolean;\n }>;\n error?: string;\n}\n\nconst pendingBatches = new Map<string, PendingBatch>();\nconst batchJobsMap = new Map<string, BatchJobState>();\nlet isRunnerRunning = false;\nlet runnerInterval: NodeJS.Timeout | null = null;\n\nexport function registerPendingBatch(batch: PendingBatch, jobState?: BatchJobState) {\n pendingBatches.set(batch.id, batch);\n if (jobState) {\n batchJobsMap.set(batch.id, jobState);\n }\n}\n\nexport function invalidateCollectionCache(uid: string) {\n modelsCache.delete(uid);\n for (const key of queryCache.keys()) {\n if (key.startsWith(`${uid}:`)) {\n queryCache.delete(key);\n }\n }\n}\n\nasync function getCollectionSignature(strapi: Core.Strapi, uid: string): Promise<string> {\n const contentType = strapi.contentTypes[uid];\n if (!contentType) return 'invalid';\n\n const isSingleType = contentType.kind === 'singleType';\n try {\n if (isSingleType) {\n const doc: any = await (strapi.documents(uid as any) as any).findFirst({\n fields: ['updatedAt', 'id'],\n });\n return doc ? `single:${doc.id}:${doc.updatedAt}` : 'single:empty';\n }\n\n const [total, latest] = await Promise.all([\n strapi.documents(uid as any).count(),\n strapi.documents(uid as any).findMany({\n limit: 1,\n sort: { updatedAt: 'desc' },\n fields: ['updatedAt', 'id'],\n }),\n ]);\n\n const latestDoc = latest && latest.length > 0 ? latest[0] : null;\n return `${total}:${latestDoc?.updatedAt || '0'}:${latestDoc?.id || '0'}`;\n } catch {\n return `${Date.now()}`;\n }\n}\n\nasync function computeTargetsSummary(strapi: Core.Strapi, { selectedCollections = [], selectedEntries = [] }: any) {\n const targetsMap = new Map<string, { uid: string; documentId: string }>();\n const breakdown: Record<string, number> = {};\n\n for (const colUid of selectedCollections) {\n const contentType = strapi.contentTypes[colUid];\n const displayName = contentType?.info?.displayName || colUid;\n try {\n const entries = await strapi.documents(colUid as any).findMany();\n const count = entries ? entries.length : 0;\n breakdown[displayName] = (breakdown[displayName] || 0) + count;\n for (const entry of (entries || []) as any[]) {\n targetsMap.set(`${colUid}@@@${entry.documentId}`, { uid: colUid, documentId: entry.documentId });\n }\n } catch {\n // Ignore count failures\n }\n }\n\n for (const item of selectedEntries) {\n if (!item.uid || !item.documentId) continue;\n const key = `${item.uid}@@@${item.documentId}`;\n if (!targetsMap.has(key)) {\n targetsMap.set(key, { uid: item.uid, documentId: item.documentId });\n const contentType = strapi.contentTypes[item.uid];\n const displayName = contentType?.info?.displayName || item.uid;\n breakdown[displayName] = (breakdown[displayName] || 0) + 1;\n }\n }\n\n return {\n totalTargets: targetsMap.size,\n collectionBreakdown: breakdown,\n };\n}\n\nasync function executeBatchInternal(\n strapi: Core.Strapi,\n {\n attribute,\n value,\n selectedEntries = [],\n selectedCollections = [],\n isRegex = false,\n regexPattern = '',\n publishOnApproval = true,\n publishStrategy = 'safe',\n unreviewedConsent = false,\n }: {\n attribute: string;\n value: string;\n selectedEntries?: Array<{ uid: string; documentId: string; dynamicZoneIndexes?: number[]; targetComponentUid?: string }>;\n selectedCollections?: string[];\n isRegex?: boolean;\n regexPattern?: string;\n publishOnApproval?: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n },\n currentUser?: any,\n existingBatchId?: string\n) {\n if (!attribute) {\n throw new Error('Attribute name is required.');\n }\n\n const targetsMap = new Map<string, { uid: string; documentId: string; dynamicZoneIndexes?: number[]; targetComponentUid?: string }>();\n\n // 1. Add entire collections if selected\n for (const colUid of selectedCollections) {\n if (!strapi.contentTypes[colUid]) continue;\n const entries = await strapi.documents(colUid as any).findMany();\n for (const entry of (entries || []) as any[]) {\n const key = `${colUid}@@@${entry.documentId}`;\n targetsMap.set(key, { uid: colUid, documentId: entry.documentId });\n }\n }\n\n // 2. Add individually selected entries\n for (const item of selectedEntries) {\n if (!item.uid || !item.documentId) continue;\n const key = `${item.uid}@@@${item.documentId}`;\n targetsMap.set(key, {\n uid: item.uid,\n documentId: item.documentId,\n dynamicZoneIndexes: item.dynamicZoneIndexes,\n targetComponentUid: item.targetComponentUid,\n });\n }\n\n if (targetsMap.size === 0) {\n throw new Error('No collections or entries were selected for update.');\n }\n\n const batchId = existingBatchId || `batch_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const results: any[] = [];\n let updatedCount = 0;\n let skippedCount = 0;\n\n const jobState: BatchJobState = {\n id: batchId,\n createdAt: new Date().toISOString(),\n startedAt: new Date().toISOString(),\n createdBy: currentUser\n ? {\n id: currentUser.id,\n email: currentUser.email,\n firstname: currentUser.firstname,\n lastname: currentUser.lastname,\n username: currentUser.username,\n }\n : { email: 'admin@system.local' },\n status: 'processing',\n executionMode: 'immediate',\n attribute,\n value,\n totalTargets: targetsMap.size,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: Boolean(publishOnApproval),\n publishStrategy,\n unreviewedConsent,\n results: [],\n };\n batchJobsMap.set(batchId, jobState);\n\n let regexObj: RegExp | null = null;\n if (isRegex && regexPattern) {\n regexObj = new RegExp(regexPattern, 'g');\n }\n\n const targets = Array.from(targetsMap.values());\n const CHUNK_SIZE = 25; // 25 concurrent updates per batch window\n\n // Request-scoped DataLoader for deduplicating lookups during batch itemization\n const documentLoader = new Map<string, Promise<any>>();\n const getDocumentDeduplicated = (uid: string, documentId: string) => {\n const loaderKey = `${uid}@@@${documentId}`;\n if (!documentLoader.has(loaderKey)) {\n documentLoader.set(\n loaderKey,\n strapi.documents(uid as any).findOne({ documentId })\n );\n }\n return documentLoader.get(loaderKey);\n };\n\n for (let i = 0; i < targets.length; i += CHUNK_SIZE) {\n const chunk = targets.slice(i, i + CHUNK_SIZE);\n const chunkPromises = chunk.map(async (target) => {\n const contentType = strapi.contentTypes[target.uid];\n const displayName = contentType?.info?.displayName || target.uid;\n\n try {\n const currentEntry: any = await getDocumentDeduplicated(target.uid, target.documentId);\n\n const entryLabel =\n currentEntry?.name ||\n currentEntry?.title ||\n currentEntry?.email ||\n `Entry #${target.documentId}`;\n\n const parsed = parseDynamicZonePath(attribute);\n const isNested = attribute.includes('.') || attribute.includes('[');\n const isComponentNested = isNested && isDeepComponentField(contentType, strapi.components, attribute);\n const parts = isNested ? parsed.cleanPath.split('.') : [];\n const rootKey = parsed.rootKey;\n const targetComponentUid = target.targetComponentUid || parsed.targetComponentUid;\n const targetIndexes = target.dynamicZoneIndexes;\n\n const attrDef = contentType?.attributes?.[attribute];\n const hasAttribute = Boolean(attrDef) || isComponentNested;\n\n if (hasAttribute) {\n if (isComponentNested) {\n // Retrieve current component state with deep populate for safe recursive merge\n const populateOption = buildDeepPopulate(contentType.attributes, strapi.components);\n const findOneArgs: any = { documentId: target.documentId };\n if (populateOption) {\n findOneArgs.populate = populateOption;\n }\n const currentEntryWithPopulate: any = await strapi.documents(target.uid as any).findOne(findOneArgs);\n const isRootDz = contentType?.attributes?.[rootKey]?.type === 'dynamiczone';\n const existingRoot = currentEntryWithPopulate?.[rootKey] || (isRootDz ? [] : {});\n\n let affectedMatches: DynamicZoneItemMatch[] = [];\n if (isRootDz && Array.isArray(existingRoot)) {\n affectedMatches = getAllNestedValues({ [rootKey]: existingRoot }, attribute);\n if (targetIndexes && targetIndexes.length > 0) {\n affectedMatches = affectedMatches.filter((m) => targetIndexes.includes(m.index));\n }\n if (targetComponentUid) {\n affectedMatches = affectedMatches.filter((m) => m.componentUid === targetComponentUid);\n }\n }\n\n const currentVal = isRootDz\n ? (affectedMatches.length > 0 ? affectedMatches.map((m) => m.value).join(', ') : getDeepProperty(existingRoot, parts.slice(1).join('.')))\n : getDeepProperty(existingRoot, parts.slice(1).join('.'));\n\n let newValue = value;\n if (regexObj && typeof currentVal === 'string') {\n newValue = currentVal.replace(regexObj, value);\n }\n\n const updatedRoot = setDeepProperty(existingRoot, parts.slice(1), newValue, {\n targetIndexes,\n targetComponentUid,\n });\n\n await strapi.documents(target.uid as any).update({\n documentId: target.documentId,\n data: {\n [rootKey]: updatedRoot,\n },\n });\n\n // If publishOnApproval is true and content type has draftAndPublish enabled, publish the document\n const isDraftAndPublishComp = Boolean(contentType?.options?.draftAndPublish);\n const isApprovedComp = isDraftAndPublishComp && Boolean(currentEntry?.publishedAt) && currentEntry?.status !== 'modified';\n const shouldPublishComp = isDraftAndPublishComp && Boolean(publishOnApproval) && (\n publishStrategy === 'all' ? true : isApprovedComp\n );\n if (shouldPublishComp) {\n try {\n await (strapi.documents(target.uid as any) as any).publish({\n documentId: target.documentId,\n });\n } catch (publishErr) {\n strapi.log.warn(`[bulk-updater] Failed to auto-publish ${target.uid}/${target.documentId}:`, publishErr);\n }\n }\n\n invalidateCollectionCache(target.uid);\n\n await recordContentHistoryVersion(strapi, {\n uid: target.uid,\n documentId: target.documentId,\n userId: currentUser?.id,\n statusOverride: shouldPublishComp ? 'published' : (isDraftAndPublishComp ? 'draft' : undefined),\n });\n\n const dzDiffs = isRootDz && affectedMatches.length > 0\n ? affectedMatches.map((m) => ({\n index: m.index,\n componentUid: m.componentUid,\n componentName: m.componentName,\n attribute: `${rootKey}[#${m.index} ${m.componentName}].${parts.slice(1).join('.')}`,\n oldValue: m.value,\n newValue: regexObj && typeof m.value === 'string' ? m.value.replace(regexObj, value) : value,\n }))\n : [];\n\n return {\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: entryLabel,\n attribute,\n oldValue: currentVal ?? null,\n newValue,\n status: 'updated' as const,\n message: isRootDz\n ? `Successfully updated ${affectedMatches.length} dynamic zone item(s) in ${attribute}`\n : `Successfully updated nested field ${attribute}`,\n dynamicZoneDiffs: dzDiffs,\n };\n }\n\n if (attrDef.type === 'relation') {\n const isMulti = attrDef.relation === 'oneToMany' || attrDef.relation === 'manyToMany';\n\n // Retrieve current relation state with populate for accurate audit logging\n const currentEntryWithPopulate: any = await strapi.documents(target.uid as any).findOne({\n documentId: target.documentId,\n populate: [attribute],\n });\n const currentRel = currentEntryWithPopulate?.[attribute];\n\n let oldDocIds: string[] = [];\n let oldDisplay = '';\n if (isMulti && Array.isArray(currentRel)) {\n oldDocIds = currentRel.map((r: any) => r.documentId).filter(Boolean);\n oldDisplay = currentRel.map((r: any) => r.name || r.title || r.email || r.documentId).join(', ') || '(empty)';\n } else if (currentRel) {\n oldDocIds = currentRel.documentId ? [currentRel.documentId] : [];\n oldDisplay = currentRel.name || currentRel.title || currentRel.email || currentRel.documentId || '(empty)';\n } else {\n oldDisplay = '(unlinked / none)';\n }\n\n // Parse relation command:\n let mode: 'set' | 'connect' | 'disconnect' | 'clear' = 'set';\n let targetDocIds: string[] = [];\n let newDisplay = '';\n\n if (value === '__clear__' || value === '') {\n mode = 'clear';\n newDisplay = '(cleared / unlinked)';\n } else {\n try {\n const parsed = JSON.parse(value);\n if (parsed && typeof parsed === 'object' && parsed.mode) {\n mode = parsed.mode;\n targetDocIds = Array.isArray(parsed.documentIds) ? parsed.documentIds : (parsed.documentId ? [parsed.documentId] : []);\n newDisplay = parsed.label || targetDocIds.join(', ') || `[${mode}]`;\n } else if (Array.isArray(parsed)) {\n targetDocIds = parsed;\n newDisplay = targetDocIds.join(', ');\n } else {\n targetDocIds = [value];\n newDisplay = value;\n }\n } catch {\n targetDocIds = [value];\n newDisplay = value;\n }\n }\n\n // Construct Document Service relation mutation payload\n let relationPayload: any;\n if (mode === 'clear') {\n relationPayload = isMulti ? { set: [] } : null;\n } else if (mode === 'set') {\n relationPayload = isMulti ? { set: targetDocIds } : (targetDocIds[0] || null);\n } else if (mode === 'connect') {\n relationPayload = { connect: targetDocIds };\n } else if (mode === 'disconnect') {\n relationPayload = { disconnect: targetDocIds };\n }\n\n await strapi.documents(target.uid as any).update({\n documentId: target.documentId,\n data: {\n [attribute]: relationPayload,\n },\n });\n\n // If publishOnApproval is true and content type has draftAndPublish enabled, publish the document\n const isDraftAndPublishRel = Boolean(contentType?.options?.draftAndPublish);\n const isApprovedRel = isDraftAndPublishRel && Boolean(currentEntry?.publishedAt) && currentEntry?.status !== 'modified';\n const shouldPublishRel = isDraftAndPublishRel && Boolean(publishOnApproval) && (\n publishStrategy === 'all' ? true : isApprovedRel\n );\n if (shouldPublishRel) {\n try {\n await (strapi.documents(target.uid as any) as any).publish({\n documentId: target.documentId,\n });\n } catch (publishErr) {\n strapi.log.warn(`[bulk-updater] Failed to auto-publish ${target.uid}/${target.documentId}:`, publishErr);\n }\n }\n\n invalidateCollectionCache(target.uid);\n if (attrDef.target) {\n invalidateCollectionCache(attrDef.target);\n }\n\n await recordContentHistoryVersion(strapi, {\n uid: target.uid,\n documentId: target.documentId,\n userId: currentUser?.id,\n statusOverride: shouldPublishRel ? 'published' : (isDraftAndPublishRel ? 'draft' : undefined),\n });\n\n return {\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: entryLabel,\n attribute,\n oldValue: { isRelation: true, documentIds: oldDocIds, display: oldDisplay },\n newValue: { isRelation: true, mode, documentIds: targetDocIds, display: newDisplay },\n status: 'updated' as const,\n message: `Successfully updated relation \"${attribute}\"`,\n };\n }\n\n let newValue = value;\n const currentVal = currentEntry?.[attribute];\n\n if (regexObj && typeof currentVal === 'string') {\n newValue = currentVal.replace(regexObj, value);\n }\n\n await strapi.documents(target.uid as any).update({\n documentId: target.documentId,\n data: {\n [attribute]: newValue,\n },\n });\n\n // If publishOnApproval is true and content type has draftAndPublish enabled, publish the document\n const isDraftAndPublishScalar = Boolean(contentType?.options?.draftAndPublish);\n const isApprovedScalar = isDraftAndPublishScalar && Boolean(currentEntry?.publishedAt) && currentEntry?.status !== 'modified';\n const shouldPublishScalar = isDraftAndPublishScalar && Boolean(publishOnApproval) && (\n publishStrategy === 'all' ? true : isApprovedScalar\n );\n if (shouldPublishScalar) {\n try {\n await (strapi.documents(target.uid as any) as any).publish({\n documentId: target.documentId,\n });\n } catch (publishErr) {\n strapi.log.warn(`[bulk-updater] Failed to auto-publish ${target.uid}/${target.documentId}:`, publishErr);\n }\n }\n\n await recordContentHistoryVersion(strapi, {\n uid: target.uid,\n documentId: target.documentId,\n userId: currentUser?.id,\n statusOverride: shouldPublishScalar ? 'published' : (isDraftAndPublishScalar ? 'draft' : undefined),\n });\n\n return {\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: entryLabel,\n attribute,\n oldValue: currentVal ?? null,\n newValue,\n status: 'updated' as const,\n message: `Successfully updated ${attribute}`,\n };\n } else {\n return {\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: entryLabel,\n attribute,\n status: 'skipped' as const,\n message: `Skipped: Attribute \"${attribute}\" does not exist in schema for ${displayName}`,\n };\n }\n } catch (updateErr: any) {\n return {\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: `Entry #${target.documentId}`,\n attribute,\n status: 'error' as const,\n message: updateErr.message,\n };\n }\n });\n\n const chunkResults = await Promise.all(chunkPromises);\n for (const res of chunkResults) {\n if (res.status === 'updated') updatedCount++;\n else if (res.status === 'skipped') skippedCount++;\n results.push(res);\n }\n jobState.processedCount = results.length;\n jobState.updatedCount = updatedCount;\n jobState.skippedCount = skippedCount;\n jobState.failedCount = results.filter((r) => r.status === 'error').length;\n }\n\n // Invalidate local in-process cache for all affected collection UIDs\n const affectedUids = new Set(targets.map((t) => t.uid));\n affectedUids.forEach((uid) => {\n invalidateCollectionCache(uid);\n });\n\n const failedCount = results.filter((r) => r.status === 'error').length;\n jobState.failedCount = failedCount;\n jobState.completedAt = new Date().toISOString();\n jobState.isLive = updatedCount > 0;\n jobState.status =\n failedCount === 0 && updatedCount > 0\n ? 'successful'\n : failedCount > 0 && updatedCount > 0\n ? 'partial_failure'\n : failedCount > 0\n ? 'failed'\n : 'successful';\n jobState.results = results.map((r) => ({\n ...r,\n isLive: r.status === 'updated',\n }));\n\n const flattenedDiffs: any[] = [];\n for (const r of results) {\n if (r.dynamicZoneDiffs && r.dynamicZoneDiffs.length > 0) {\n for (const dz of r.dynamicZoneDiffs) {\n flattenedDiffs.push({\n uid: r.uid,\n collectionName: r.collectionName,\n documentId: r.documentId,\n label: `${r.label} [Block #${dz.index} (${dz.componentName})]`,\n attribute: dz.attribute,\n oldValue: dz.oldValue,\n newValue: dz.newValue,\n status: 'updated',\n message: `Updated ${dz.attribute}`,\n });\n }\n } else {\n flattenedDiffs.push(r);\n }\n }\n\n const batchSummary = {\n batchId,\n attribute,\n value,\n updatedCount,\n skippedCount,\n totalTargets: targetsMap.size,\n publishOnApproval,\n publishStrategy,\n unreviewedConsent,\n };\n\n // Stateless audit recording via consumer's declared audit schema\n await strapi.plugin('bulk-updater').service('audit').recordBatch(\n batchSummary,\n flattenedDiffs,\n currentUser\n );\n\n return {\n success: true,\n batchId,\n attribute,\n value,\n updatedCount,\n skippedCount,\n failedCount,\n totalTargets: targetsMap.size,\n isLive: jobState.isLive,\n status: jobState.status,\n results,\n };\n}\n\n/**\n * Executes a bulk publish operation directly across selected entries and collections.\n */\nasync function executePublishBatchInternal(\n strapi: Core.Strapi,\n {\n selectedEntries = [],\n selectedCollections = [],\n unreviewedConsent = false,\n }: {\n selectedEntries?: Array<{ uid: string; documentId: string }>;\n selectedCollections?: string[];\n unreviewedConsent?: boolean;\n },\n currentUser?: any,\n existingBatchId?: string\n) {\n const targetsMap = new Map<string, { uid: string; documentId: string }>();\n\n // 1. Add entire collections if selected\n for (const colUid of selectedCollections) {\n if (!strapi.contentTypes[colUid]) continue;\n const entries = await (strapi.documents(colUid as any) as any).findMany();\n for (const entry of (entries || []) as any[]) {\n const key = `${colUid}@@@${entry.documentId}`;\n targetsMap.set(key, { uid: colUid, documentId: entry.documentId });\n }\n }\n\n // 2. Add individually selected entries\n for (const item of selectedEntries) {\n if (!item.uid || !item.documentId) continue;\n const key = `${item.uid}@@@${item.documentId}`;\n targetsMap.set(key, { uid: item.uid, documentId: item.documentId });\n }\n\n if (targetsMap.size === 0) {\n throw new Error('No collections or entries were selected to publish.');\n }\n\n const batchId = existingBatchId || `batch_pub_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const results: any[] = [];\n let publishedCount = 0;\n let skippedCount = 0;\n\n const jobState: BatchJobState = {\n id: batchId,\n createdAt: new Date().toISOString(),\n startedAt: new Date().toISOString(),\n createdBy: currentUser\n ? {\n id: currentUser.id,\n email: currentUser.email,\n firstname: currentUser.firstname,\n lastname: currentUser.lastname,\n username: currentUser.username,\n }\n : { email: 'admin@system.local' },\n status: 'processing',\n executionMode: 'immediate',\n attribute: '(publish)',\n value: 'published',\n totalTargets: targetsMap.size,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: true,\n unreviewedConsent,\n results: [],\n };\n batchJobsMap.set(batchId, jobState);\n\n const targets = Array.from(targetsMap.values());\n const CHUNK_SIZE = 25;\n\n for (let i = 0; i < targets.length; i += CHUNK_SIZE) {\n const chunk = targets.slice(i, i + CHUNK_SIZE);\n\n const chunkPromises = chunk.map(async (target) => {\n try {\n const contentType = strapi.contentTypes[target.uid];\n const displayName = contentType?.info?.displayName || target.uid;\n const isDraftAndPublish = Boolean(contentType?.options?.draftAndPublish);\n\n let existingDoc: any = null;\n try {\n existingDoc = await (strapi.documents(target.uid as any) as any).findOne({\n documentId: target.documentId,\n });\n } catch {\n existingDoc = null;\n }\n\n const entryLabel =\n existingDoc?.name ||\n existingDoc?.title ||\n existingDoc?.label ||\n existingDoc?.documentId ||\n `Entry #${target.documentId}`;\n\n if (!isDraftAndPublish) {\n return {\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: entryLabel,\n attribute: '(publish)',\n status: 'skipped' as const,\n message: `Skipped: Draft & Publish is disabled for collection ${displayName}`,\n };\n }\n\n const isAlreadyPublished = Boolean(existingDoc?.publishedAt);\n\n await (strapi.documents(target.uid as any) as any).publish({\n documentId: target.documentId,\n });\n\n invalidateCollectionCache(target.uid);\n\n await recordContentHistoryVersion(strapi, {\n uid: target.uid,\n documentId: target.documentId,\n userId: currentUser?.id,\n statusOverride: 'published',\n });\n\n return {\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: entryLabel,\n attribute: '(publish)',\n oldValue: isAlreadyPublished ? 'published' : 'draft',\n newValue: 'published',\n status: 'updated' as const,\n message: isAlreadyPublished\n ? 'Re-published latest version live'\n : 'Successfully published to live',\n };\n } catch (pubErr: any) {\n return {\n uid: target.uid,\n collectionName: strapi.contentTypes[target.uid]?.info?.displayName || target.uid,\n documentId: target.documentId,\n label: `Entry #${target.documentId}`,\n attribute: '(publish)',\n status: 'error' as const,\n message: pubErr.message || 'Failed to publish entry',\n };\n }\n });\n\n const chunkResults = await Promise.all(chunkPromises);\n for (const res of chunkResults) {\n if (res.status === 'updated') publishedCount++;\n else if (res.status === 'skipped') skippedCount++;\n results.push(res);\n }\n jobState.processedCount = results.length;\n jobState.updatedCount = publishedCount;\n jobState.skippedCount = skippedCount;\n jobState.failedCount = results.filter((r) => r.status === 'error').length;\n }\n\n const affectedUids = new Set(targets.map((t) => t.uid));\n affectedUids.forEach((uid) => {\n invalidateCollectionCache(uid);\n });\n\n const failedCount = results.filter((r) => r.status === 'error').length;\n jobState.failedCount = failedCount;\n jobState.completedAt = new Date().toISOString();\n jobState.isLive = publishedCount > 0;\n jobState.status =\n failedCount === 0 && publishedCount > 0\n ? 'successful'\n : failedCount > 0 && publishedCount > 0\n ? 'partial_failure'\n : failedCount > 0\n ? 'failed'\n : 'successful';\n jobState.results = results.map((r) => ({\n ...r,\n isLive: r.status === 'updated',\n }));\n\n const batchSummary = {\n batchId,\n attribute: '(publish)',\n value: 'published',\n updatedCount: publishedCount,\n skippedCount,\n totalTargets: targetsMap.size,\n publishOnApproval: true,\n unreviewedConsent,\n };\n\n // Stateless audit recording\n await strapi.plugin('bulk-updater').service('audit').recordBatch(\n batchSummary,\n results,\n currentUser\n );\n\n return {\n success: true,\n batchId,\n publishedCount,\n updatedCount: publishedCount,\n skippedCount,\n failedCount,\n totalTargets: targetsMap.size,\n isLive: publishedCount > 0,\n status: jobState.status,\n results,\n };\n}\n\nasync function executeBatchByPayload(\n strapi: Core.Strapi,\n batch: PendingBatch,\n currentUser: any\n) {\n if (batch.payload?.action === 'csv_import') {\n const csvService = strapi.plugin('bulk-updater').service('csv');\n return await csvService.executeCsvPendingBatch(\n batch.payload.uid,\n batch.payload.rows,\n batch.id,\n batch.payload.options,\n currentUser\n );\n } else if (batch.payload?.action === 'publish') {\n return await executePublishBatchInternal(strapi, batch.payload, currentUser, batch.id);\n } else {\n return await executeBatchInternal(strapi, batch.payload, currentUser, batch.id);\n }\n}\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => {\n // Initialize periodic runner for off-peak queue execution\n if (!runnerInterval) {\n runnerInterval = setInterval(async () => {\n if (isRunnerRunning) return;\n isRunnerRunning = true;\n try {\n const config = getExecutionWindowConfig(strapi);\n const { isBusinessHours } = checkBusinessHours(config);\n\n for (const [id, batch] of pendingBatches.entries()) {\n if (batch.status === 'queued_offpeak' && !isBusinessHours) {\n strapi.log.info(`[bulk-updater] Executing off-peak queued batch: ${id}`);\n const result = await executeBatchByPayload(strapi, batch, batch.createdBy);\n batch.status = 'executed';\n batch.executionResult = result;\n }\n }\n } catch (err) {\n strapi.log.error('[bulk-updater] Scheduled runner error:', err);\n } finally {\n isRunnerRunning = false;\n }\n }, 30000);\n }\n\n return {\n /**\n * Lightweight Schema Discovery:\n * Returns schema definitions, valid attributes, and total counts (<15KB payload)\n * Previews up to 10 entries per collection to ensure instantaneous initial paint.\n * Utilizes in-memory schema memoization and database high-watermark signature caching.\n */\n async getModels() {\n const allContentTypes = strapi.contentTypes || {};\n const auditConfig = strapi.plugin('bulk-updater').service('audit').getAuditConfig();\n const auditContentType = auditConfig?.contentType;\n\n // 1. Static schema discovery memoized in-memory\n if (!staticSchemaCache) {\n const allAttributesSet = new Set<string>();\n const systemFields = [\n 'createdAt',\n 'updatedAt',\n 'publishedAt',\n 'createdBy',\n 'updatedBy',\n 'locale',\n 'localizations',\n ];\n\n const configuredCollections = strapi.config.get(\n 'plugin::bulk-updater.collections'\n ) as string[] | string | undefined;\n\n const isWildcard =\n configuredCollections === '*' ||\n configuredCollections === 'all' ||\n (Array.isArray(configuredCollections) &&\n (configuredCollections.includes('*') || configuredCollections.includes('all')));\n\n let targetUids: string[];\n if (\n !isWildcard &&\n configuredCollections &&\n Array.isArray(configuredCollections) &&\n configuredCollections.length > 0\n ) {\n targetUids = configuredCollections.filter((uid) => uid in allContentTypes);\n } else {\n targetUids = Object.keys(allContentTypes).filter(\n (uid) =>\n uid.startsWith('api::') &&\n !uid.includes('bulk-updater') &&\n uid !== auditContentType\n );\n }\n\n const metaByUid: Record<string, any> = {};\n const allRelationsMeta: Record<string, RelationMeta> = {};\n const allAttributesMeta: Record<string, AttributeMeta> = {};\n\n for (const uid of targetUids) {\n const contentType = allContentTypes[uid];\n if (!contentType || (contentType.kind !== 'collectionType' && contentType.kind !== 'singleType')) continue;\n\n const isSingleType = contentType.kind === 'singleType';\n const rawAttrs = contentType.attributes || {};\n const relationsByAttr: Record<string, RelationMeta> = {};\n const colAttributesMeta: Record<string, AttributeMeta> = {};\n const nestedComponentAttrs: string[] = [];\n\n const validAttrs = Object.keys(rawAttrs).filter((attrKey) => {\n if (systemFields.includes(attrKey)) return false;\n\n if (rawAttrs[attrKey].type === 'dynamiczone') {\n const dzDef = rawAttrs[attrKey];\n const dzComponents = Array.isArray(dzDef.components) ? dzDef.components : [];\n for (const compUid of dzComponents) {\n // Generic path across all components (e.g. blocks.title)\n const compAttrs = discoverComponentAttributes(\n strapi,\n compUid,\n attrKey,\n 1,\n 5,\n systemFields,\n allContentTypes,\n relationsByAttr,\n allRelationsMeta,\n colAttributesMeta\n );\n nestedComponentAttrs.push(...compAttrs);\n\n // Component-scoped path (e.g. blocks[shared.heading].title)\n const scopedAttrs = discoverComponentAttributes(\n strapi,\n compUid,\n `${attrKey}[${compUid}]`,\n 1,\n 5,\n systemFields,\n allContentTypes,\n relationsByAttr,\n allRelationsMeta,\n colAttributesMeta\n );\n nestedComponentAttrs.push(...scopedAttrs);\n }\n return false;\n }\n\n if (rawAttrs[attrKey].type === 'component') {\n const compDef = rawAttrs[attrKey];\n if (compDef.component) {\n const compAttrs = discoverComponentAttributes(\n strapi,\n compDef.component,\n attrKey,\n 1,\n 5,\n systemFields,\n allContentTypes,\n relationsByAttr,\n allRelationsMeta,\n colAttributesMeta\n );\n nestedComponentAttrs.push(...compAttrs);\n }\n return false;\n }\n\n if (rawAttrs[attrKey].type === 'relation') {\n const rel = rawAttrs[attrKey];\n const targetUid = rel.target;\n if (!targetUid || !allContentTypes[targetUid]) return false;\n const targetInfo = allContentTypes[targetUid]?.info;\n const isMulti = rel.relation === 'oneToMany' || rel.relation === 'manyToMany';\n const relMeta: RelationMeta = {\n isRelation: true,\n relationType: rel.relation,\n targetUid,\n targetDisplayName: targetInfo?.displayName || targetUid,\n isMulti,\n };\n relationsByAttr[attrKey] = relMeta;\n allRelationsMeta[attrKey] = relMeta;\n colAttributesMeta[attrKey] = { depth: 0, type: 'relation', isRelation: true };\n return true;\n }\n\n colAttributesMeta[attrKey] = { depth: 0, type: rawAttrs[attrKey].type };\n return true;\n });\n\n const allColAttrs = Array.from(new Set([...validAttrs, ...nestedComponentAttrs]));\n allColAttrs.forEach((attr) => {\n allAttributesSet.add(attr);\n if (colAttributesMeta[attr]) {\n allAttributesMeta[attr] = colAttributesMeta[attr];\n }\n });\n\n metaByUid[uid] = {\n uid,\n kind: contentType.kind,\n isSingleType,\n draftAndPublish: Boolean(contentType.options?.draftAndPublish),\n singularName: contentType.info?.singularName || uid,\n pluralName: contentType.info?.pluralName || uid,\n displayName: contentType.info?.displayName || uid,\n attributes: allColAttrs,\n attributesMeta: colAttributesMeta,\n relations: relationsByAttr,\n };\n }\n\n staticSchemaCache = {\n attributes: Array.from(allAttributesSet),\n attributesMeta: allAttributesMeta,\n targetUids: Object.keys(metaByUid),\n metaByUid,\n relationsMeta: allRelationsMeta,\n };\n }\n\n const collections = [];\n const signatures: string[] = [];\n\n // 2. High-watermark check per collection with throttled concurrency (batches of 10)\n // Prevents database connection pool exhaustion and file locks on 100+ collection schemas\n const BATCH_CONCURRENCY = 10;\n const collectionResults: Array<any> = [];\n\n for (let i = 0; i < staticSchemaCache.targetUids.length; i += BATCH_CONCURRENCY) {\n const batchUids = staticSchemaCache.targetUids.slice(i, i + BATCH_CONCURRENCY);\n const batchRes = await Promise.all(\n batchUids.map(async (uid) => {\n const meta = staticSchemaCache!.metaByUid[uid];\n if (!meta) return null;\n\n const signature = await getCollectionSignature(strapi, uid);\n const cached = modelsCache.get(uid);\n if (cached && cached.signature === signature) {\n return {\n collection: {\n ...meta,\n totalEntries: cached.totalCount,\n entries: cached.entries,\n },\n signature: `${uid}=${signature}`,\n };\n }\n\n let entries: any[] = [];\n let totalCount = 0;\n try {\n const populateOption = buildDeepPopulate(allContentTypes[uid]?.attributes || {}, strapi.components);\n\n if (meta.isSingleType) {\n const singleArgs: any = {};\n if (populateOption) {\n singleArgs.populate = populateOption;\n }\n const singleDoc: any = await (strapi.documents(uid as any) as any).findFirst(singleArgs);\n if (singleDoc) {\n entries = [singleDoc];\n totalCount = 1;\n }\n } else {\n totalCount = await strapi.documents(uid as any).count();\n const findArgs: any = {\n limit: 10,\n sort: { createdAt: 'desc' },\n };\n if (populateOption) {\n findArgs.populate = populateOption;\n }\n entries = await strapi.documents(uid as any).findMany(findArgs);\n }\n } catch (err) {\n strapi.log.error(`[bulk-updater] Failed to fetch entries for ${uid}:`, err);\n entries = [];\n totalCount = 0;\n }\n\n const formattedEntries = (entries || []).map(formatEntryRecord);\n\n modelsCache.set(uid, {\n signature,\n totalCount,\n entries: formattedEntries,\n });\n\n return {\n collection: {\n ...meta,\n totalEntries: totalCount,\n entries: formattedEntries,\n },\n signature: `${uid}=${signature}`,\n };\n })\n );\n collectionResults.push(...batchRes);\n }\n\n for (const res of collectionResults) {\n if (res) {\n collections.push(res.collection);\n signatures.push(res.signature);\n }\n }\n\n const executionConfig = getExecutionWindowConfig(strapi);\n const windowStatus = checkBusinessHours(executionConfig);\n const pendingCount = Array.from(pendingBatches.values()).filter(\n (b) => b.status === 'pending_approval' || b.status === 'queued_offpeak'\n ).length;\n\n const etag = `W/\"models-${crypto.createHash('md5').update(`${signatures.join('|')}:${pendingCount}:${windowStatus.isBusinessHours}:${windowStatus.currentServerTime}:${windowStatus.timeZone}`).digest('hex')}\"`;\n\n return {\n success: true,\n attributes: staticSchemaCache.attributes,\n attributesMeta: staticSchemaCache.attributesMeta,\n collections,\n relationsMeta: staticSchemaCache.relationsMeta,\n maxDiscoveredDepth: 5,\n executionWindow: {\n ...executionConfig,\n ...windowStatus,\n },\n pendingBatchesCount: pendingCount,\n auditEnabled: Boolean(auditConfig?.enabled),\n etag,\n };\n },\n\n /**\n * On-Demand Paginated Collection Entries:\n * Supports server-side pagination (limit / start) and database query pushdown for filters.\n * Cached in-process with cross-pod high-watermark signature validation.\n */\n async getCollectionEntries(\n uid: string,\n {\n page = 1,\n pageSize = 10,\n attribute,\n searchAttribute,\n filterOperator,\n filterQuery,\n search,\n sortField,\n sortOrder = 'desc',\n }: {\n page?: number;\n pageSize?: number;\n attribute?: string;\n searchAttribute?: string;\n filterOperator?: string;\n filterQuery?: string;\n search?: string;\n sortField?: string;\n sortOrder?: 'asc' | 'desc';\n }\n ) {\n const contentType = strapi.contentTypes[uid];\n if (!contentType) {\n throw new Error(`Collection with UID \"${uid}\" does not exist.`);\n }\n\n const limit = Math.min(Math.max(Number(pageSize) || 10, 1), 500);\n const currentPage = Math.max(Number(page) || 1, 1);\n const start = (currentPage - 1) * limit;\n\n const isSingleType = contentType.kind === 'singleType';\n const targetFilterAttr = searchAttribute || attribute;\n\n // 1. Signature-based caching verification\n const signature = await getCollectionSignature(strapi, uid);\n const cacheKey = `${uid}:${limit}:${start}:${attribute || ''}:${searchAttribute || ''}:${filterOperator || ''}:${filterQuery || ''}:${search || ''}:${sortField || ''}:${sortOrder}`;\n const cached = queryCache.get(cacheKey);\n\n const etag = `W/\"entry-${crypto.createHash('md5').update(`${cacheKey}:${signature}`).digest('hex')}\"`;\n\n if (cached && cached.signature === signature && Date.now() - cached.timestamp < CACHE_TTL_MS) {\n return {\n ...cached.data,\n cached: true,\n etag,\n };\n }\n\n let result: any;\n\n // Build database filters pushdown\n const filters: Record<string, any> = {};\n\n const attrs = contentType.attributes || {};\n let colHasAttribute = false;\n let isNestedAttr = false;\n let isRootDz = false;\n let parts: string[] = [];\n\n let resolvedFilterAttr = targetFilterAttr;\n if (targetFilterAttr) {\n const resolvedField = resolveContentTypeField(contentType, targetFilterAttr);\n if (resolvedField) {\n resolvedFilterAttr = resolvedField;\n colHasAttribute = true;\n } else {\n const parsed = parseDynamicZonePath(targetFilterAttr);\n if (parsed.rootKey && contentType.attributes?.[parsed.rootKey]?.type === 'dynamiczone') {\n isRootDz = true;\n colHasAttribute = true;\n isNestedAttr = true;\n parts = parsed.cleanPath.split('.');\n } else if (targetFilterAttr.includes('.') || targetFilterAttr.includes('[')) {\n isNestedAttr = isDeepComponentField(contentType, strapi.components, targetFilterAttr);\n if (isNestedAttr) {\n colHasAttribute = true;\n parts = parsed.cleanPath.split('.');\n }\n }\n }\n }\n\n const normOp = (filterOperator || '').toLowerCase().replace(/_/g, '');\n\n // If a specific attribute filter is active, check if the collection actually has the attribute\n if (normOp && normOp !== 'none') {\n if (!colHasAttribute) {\n // Collection does not possess this attribute: return 0 matching entries\n result = {\n uid,\n displayName: contentType.info?.displayName || uid,\n isSingleType,\n draftAndPublish: Boolean(contentType.options?.draftAndPublish),\n entries: [],\n pagination: {\n page: 1,\n pageSize: limit,\n total: 0,\n pageCount: 0,\n },\n };\n queryCache.set(cacheKey, { signature, data: result, timestamp: Date.now() });\n return { ...result, cached: false, etag };\n }\n\n let condition: any = undefined;\n const q = (filterQuery || '').trim();\n\n const targetAttrSchema = isNestedAttr\n ? getLeafAttributeSchema(contentType, strapi.components, targetFilterAttr)\n : attrs[resolvedFilterAttr];\n const isRelation = targetAttrSchema?.type === 'relation';\n const isStringLike = ['string', 'text', 'email', 'richtext', 'uid'].includes(targetAttrSchema?.type);\n\n if (isRelation) {\n const targetUid = targetAttrSchema?.target;\n const targetContentType = targetUid ? strapi.contentTypes[targetUid] : undefined;\n const targetAttrs = targetContentType?.attributes || {};\n const targetStringAttrs = Object.keys(targetAttrs).filter((k) =>\n ['string', 'text', 'email', 'uid'].includes(targetAttrs[k]?.type)\n );\n\n if (normOp === 'empty') {\n condition = { documentId: { $null: true } };\n } else if (normOp === 'notempty') {\n condition = { documentId: { $notNull: true } };\n } else if (q !== '') {\n const orConditions: any[] = [];\n targetStringAttrs.slice(0, 5).forEach((k) => {\n if (normOp === 'equals') {\n orConditions.push({ [k]: { $eqi: q } });\n } else if (normOp === 'startswith') {\n orConditions.push({ [k]: { $startsWithi: q } });\n } else if (normOp === 'endswith') {\n orConditions.push({ [k]: { $endsWithi: q } });\n } else if (normOp === 'notequals') {\n orConditions.push({ [k]: { $nei: q } });\n } else if (normOp === 'notcontains') {\n orConditions.push({ [k]: { $notContainsi: q } });\n } else {\n orConditions.push({ [k]: { $containsi: q } });\n }\n });\n orConditions.push({ documentId: { $eq: q } });\n if (/^\\d+$/.test(q)) {\n orConditions.push({ id: { $eq: Number(q) } });\n }\n condition = orConditions.length === 1 ? orConditions[0] : { $or: orConditions };\n }\n } else if (normOp === 'empty') {\n condition = isStringLike ? { $or: [{ $null: true }, { $eq: '' }] } : { $null: true };\n } else if (normOp === 'notempty') {\n condition = isStringLike ? { $and: [{ $notNull: true }, { $ne: '' }] } : { $notNull: true };\n } else if (q !== '') {\n let typedVal: any = q;\n const isNumeric = ['integer', 'biginteger', 'float', 'decimal', 'number'].includes(targetAttrSchema?.type);\n const isBoolean = targetAttrSchema?.type === 'boolean';\n if (isNumeric && /^-?\\d+(\\.\\d+)?$/.test(q)) {\n typedVal = Number(q);\n } else if (isBoolean) {\n if (q.toLowerCase() === 'true') typedVal = true;\n else if (q.toLowerCase() === 'false') typedVal = false;\n }\n\n switch (normOp) {\n case 'equals':\n condition = isStringLike ? { $eqi: q } : { $eq: typedVal };\n break;\n case 'notequals':\n condition = isStringLike ? { $nei: q } : { $ne: typedVal };\n break;\n case 'contains':\n condition = { $containsi: q };\n break;\n case 'notcontains':\n condition = { $notContainsi: q };\n break;\n case 'startswith':\n condition = { $startsWithi: q };\n break;\n case 'endswith':\n condition = { $endsWithi: q };\n break;\n }\n }\n\n if (condition !== undefined) {\n if (isNestedAttr) {\n if (isRootDz) {\n // Dynamic zones cannot be filtered via database pushdown in Strapi 5 (causes \"Invalid key <zone>\").\n // Evaluated in-memory across all components after fetching entries.\n } else {\n const deepFilter = buildDeepFilter(parts, condition);\n Object.assign(filters, deepFilter);\n }\n } else {\n if (normOp === 'empty' && isStringLike) {\n filters.$or = [\n { [resolvedFilterAttr]: { $null: true } },\n { [resolvedFilterAttr]: { $eq: '' } },\n ];\n } else if (normOp === 'notempty' && isStringLike) {\n filters[resolvedFilterAttr] = { $notNull: true, $ne: '' };\n } else {\n filters[resolvedFilterAttr] = condition;\n }\n }\n }\n }\n\n if (search && search.trim() !== '') {\n const q = search.trim();\n const searchableAttrs = Object.keys(attrs).filter((k) =>\n ['string', 'text', 'email', 'uid'].includes(attrs[k]?.type)\n );\n\n if (searchableAttrs.length > 0) {\n const orList = searchableAttrs.slice(0, 6).map((k) => ({\n [k]: { $containsi: q },\n }));\n\n if (Object.keys(filters).length > 0) {\n const existingFilters = { ...filters };\n Object.keys(filters).forEach((k) => delete filters[k]);\n filters.$and = [existingFilters, { $or: orList }];\n } else {\n filters.$or = orList;\n }\n }\n }\n\n const populateOption = buildDeepPopulate(contentType.attributes, strapi.components);\n\n if (isSingleType) {\n let singleDoc: any = null;\n try {\n const singleArgs: any = {\n filters: Object.keys(filters).length > 0 ? filters : undefined,\n };\n if (populateOption) {\n singleArgs.populate = populateOption;\n }\n singleDoc = await (strapi.documents(uid as any) as any).findFirst(singleArgs);\n } catch {\n singleDoc = null;\n }\n result = {\n uid,\n displayName: contentType.info?.displayName || uid,\n isSingleType: true,\n draftAndPublish: Boolean(contentType.options?.draftAndPublish),\n entries: singleDoc ? [formatEntryRecord(singleDoc)] : [],\n pagination: {\n page: 1,\n pageSize: 1,\n total: singleDoc ? 1 : 0,\n pageCount: singleDoc ? 1 : 0,\n },\n };\n } else {\n let sortClause: any = {};\n if (sortField && sortField.includes('.')) {\n const sortParts = sortField.split('.');\n if (isDeepComponentField(contentType, strapi.components, sortField)) {\n sortClause = buildDeepFilter(sortParts, sortOrder);\n } else {\n sortClause['createdAt'] = 'desc';\n }\n } else if (sortField) {\n const resolvedField = resolveContentTypeField(contentType, sortField);\n if (resolvedField) {\n sortClause[resolvedField] = sortOrder;\n } else {\n sortClause['createdAt'] = 'desc';\n }\n } else {\n sortClause['createdAt'] = 'desc';\n }\n\n if (isRootDz && normOp && normOp !== 'none') {\n // Dynamic zone filter active: fetch candidates safely and filter in-memory across all components\n const findManyArgs: any = {\n limit: 500,\n filters: Object.keys(filters).length > 0 ? filters : undefined,\n sort: sortClause,\n };\n if (populateOption) {\n findManyArgs.populate = populateOption;\n }\n\n const rawEntries = await strapi.documents(uid as any).findMany(findManyArgs);\n const qVal = (filterQuery || '').trim().toLowerCase();\n\n const passesDzFilter = (entry: any) => {\n const matches = getAllNestedValues(entry, targetFilterAttr);\n if (normOp === 'empty') {\n return matches.length === 0 || matches.every((m) => {\n const v = m.value;\n if (v === undefined || v === null) return true;\n if (Array.isArray(v)) return v.length === 0;\n if (typeof v === 'object') return Object.keys(v).length === 0;\n return String(v).trim() === '';\n });\n }\n if (normOp === 'notempty') {\n return matches.some((m) => {\n const v = m.value;\n if (v === undefined || v === null) return false;\n if (Array.isArray(v)) return v.length > 0;\n if (typeof v === 'object') return Object.keys(v).length > 0;\n return String(v).trim() !== '';\n });\n }\n\n const testSingleValue = (v: any): boolean => {\n if (v === undefined || v === null) return false;\n if (Array.isArray(v)) return v.some(testSingleValue);\n if (typeof v === 'object') {\n return (\n testSingleValue(v.name) ||\n testSingleValue(v.title) ||\n testSingleValue(v.email) ||\n testSingleValue(v.username) ||\n testSingleValue(v.documentId) ||\n testSingleValue(v.id) ||\n testSingleValue(v.slug)\n );\n }\n const valStr = String(v).trim().toLowerCase();\n switch (normOp) {\n case 'equals': return valStr === qVal;\n case 'notequals': return valStr !== qVal;\n case 'contains': return valStr.includes(qVal);\n case 'notcontains': return !valStr.includes(qVal);\n case 'startswith': return valStr.startsWith(qVal);\n case 'endswith': return valStr.endsWith(qVal);\n default: return true;\n }\n };\n\n return matches.some((m) => testSingleValue(m.value));\n };\n\n const matchedEntries = (rawEntries || []).filter(passesDzFilter);\n const totalEntries = matchedEntries.length;\n const paginatedEntries = matchedEntries.slice(start, start + limit);\n\n result = {\n uid,\n displayName: contentType.info?.displayName || uid,\n isSingleType: false,\n draftAndPublish: Boolean(contentType.options?.draftAndPublish),\n entries: paginatedEntries.map(formatEntryRecord),\n pagination: {\n page: currentPage,\n pageSize: limit,\n total: totalEntries,\n pageCount: Math.ceil(totalEntries / limit) || 1,\n },\n };\n } else {\n const findManyArgs: any = {\n start,\n limit,\n filters: Object.keys(filters).length > 0 ? filters : undefined,\n sort: sortClause,\n };\n if (populateOption) {\n findManyArgs.populate = populateOption;\n }\n\n const [entries, totalEntries] = await Promise.all([\n strapi.documents(uid as any).findMany(findManyArgs),\n strapi.documents(uid as any).count({\n filters: Object.keys(filters).length > 0 ? filters : undefined,\n }),\n ]);\n\n result = {\n uid,\n displayName: contentType.info?.displayName || uid,\n isSingleType: false,\n draftAndPublish: Boolean(contentType.options?.draftAndPublish),\n entries: (entries || []).map(formatEntryRecord),\n pagination: {\n page: currentPage,\n pageSize: limit,\n total: totalEntries,\n pageCount: Math.ceil(totalEntries / limit) || 1,\n },\n };\n }\n }\n\n // Store in queryCache with bounding limit\n if (queryCache.size >= MAX_QUERY_CACHE_SIZE) {\n const toDelete = Array.from(queryCache.keys()).slice(0, 100);\n toDelete.forEach((k) => queryCache.delete(k));\n }\n queryCache.set(cacheKey, { signature, data: result, timestamp: Date.now() });\n\n return {\n ...result,\n cached: false,\n etag,\n };\n },\n\n /**\n * Get available target entities for a relation field:\n * Cached in-process with cross-pod signature validation.\n */\n async getRelationOptions(targetUid: string) {\n if (!targetUid || !strapi.contentTypes[targetUid]) {\n throw new Error(`Target content type \"${targetUid}\" does not exist.`);\n }\n\n const cacheKey = `rel_options:${targetUid}`;\n const signature = await getCollectionSignature(strapi, targetUid);\n const cached = queryCache.get(cacheKey);\n if (cached && cached.signature === signature) {\n return cached.data;\n }\n\n const docs = await strapi.documents(targetUid as any).findMany({\n limit: 100,\n sort: { createdAt: 'desc' },\n });\n\n const options = (docs || []).map((doc: any) => {\n const label = doc.name || doc.title || doc.email || doc.username || `Entry #${doc.id || doc.documentId}`;\n return {\n documentId: doc.documentId,\n label,\n };\n });\n\n const result = { targetUid, options };\n queryCache.set(cacheKey, { signature, data: result, timestamp: Date.now() });\n return result;\n },\n\n /**\n * Preview bulk update changes before execution:\n * Reads current values and computes proposed new values without mutating data.\n */\n async previewBatch({\n attribute,\n value,\n selectedEntries = [],\n selectedCollections = [],\n isRegex = false,\n regexPattern = '',\n }: {\n attribute: string;\n value: string;\n selectedEntries?: Array<{ uid: string; documentId: string; dynamicZoneIndexes?: number[]; targetComponentUid?: string }>;\n selectedCollections?: string[];\n isRegex?: boolean;\n regexPattern?: string;\n }) {\n if (!attribute) {\n throw new Error('Attribute name is required.');\n }\n\n const targetsMap = new Map<string, { uid: string; documentId: string; dynamicZoneIndexes?: number[]; targetComponentUid?: string }>();\n\n // 1. Add entire collections if selected\n for (const colUid of selectedCollections) {\n if (!strapi.contentTypes[colUid]) continue;\n const entries = await strapi.documents(colUid as any).findMany();\n for (const entry of (entries || []) as any[]) {\n const key = `${colUid}@@@${entry.documentId}`;\n targetsMap.set(key, { uid: colUid, documentId: entry.documentId });\n }\n }\n\n // 2. Add individually selected entries\n for (const item of selectedEntries) {\n if (!item.uid || !item.documentId) continue;\n const key = `${item.uid}@@@${item.documentId}`;\n targetsMap.set(key, {\n uid: item.uid,\n documentId: item.documentId,\n dynamicZoneIndexes: item.dynamicZoneIndexes,\n targetComponentUid: item.targetComponentUid,\n });\n }\n\n if (targetsMap.size === 0) {\n throw new Error('No collections or entries were selected for preview.');\n }\n\n let regexObj: RegExp | null = null;\n if (isRegex && regexPattern) {\n try {\n regexObj = new RegExp(regexPattern, 'g');\n } catch (e: any) {\n throw new Error(`Invalid regular expression: ${e.message}`);\n }\n }\n\n const targets = Array.from(targetsMap.values());\n const diffs: any[] = [];\n let willUpdateCount = 0;\n let unchangedCount = 0;\n let skippedCount = 0;\n\n for (const target of targets) {\n const contentType = strapi.contentTypes[target.uid];\n const displayName = contentType?.info?.displayName || target.uid;\n\n try {\n const isNested = attribute.includes('.');\n const isComponentNested = isNested && isDeepComponentField(contentType, strapi.components, attribute);\n\n const attrDef = contentType?.attributes?.[attribute];\n const hasAttribute = Boolean(attrDef) || isComponentNested;\n\n if (!hasAttribute) {\n skippedCount++;\n diffs.push({\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: `Entry #${target.documentId}`,\n attribute,\n oldValue: null,\n newValue: null,\n oldDisplay: '—',\n newDisplay: '—',\n hasChange: false,\n status: 'will_skip',\n message: `Attribute \"${attribute}\" does not exist in schema for ${displayName}`,\n });\n continue;\n }\n\n let currentEntry: any;\n if (isComponentNested) {\n const findOneArgs: any = { documentId: target.documentId };\n const populateOption = buildDeepPopulate(contentType.attributes, strapi.components);\n if (populateOption) {\n findOneArgs.populate = populateOption;\n }\n currentEntry = await strapi.documents(target.uid as any).findOne(findOneArgs);\n } else if (attrDef?.type === 'relation') {\n currentEntry = await strapi.documents(target.uid as any).findOne({\n documentId: target.documentId,\n populate: [attribute],\n });\n } else {\n currentEntry = await strapi.documents(target.uid as any).findOne({\n documentId: target.documentId,\n });\n }\n\n const entryLabel =\n currentEntry?.name ||\n currentEntry?.title ||\n currentEntry?.email ||\n `Entry #${target.documentId}`;\n\n if (isComponentNested) {\n const parsed = parseDynamicZonePath(attribute);\n const rootKey = parsed.rootKey;\n const isRootDz = contentType?.attributes?.[rootKey]?.type === 'dynamiczone';\n const targetIndexes = target.dynamicZoneIndexes;\n const targetComponentUid = target.targetComponentUid || parsed.targetComponentUid;\n\n if (isRootDz && currentEntry?.[rootKey] && Array.isArray(currentEntry[rootKey])) {\n let affectedMatches = getAllNestedValues({ [rootKey]: currentEntry[rootKey] }, attribute);\n if (targetIndexes && targetIndexes.length > 0) {\n affectedMatches = affectedMatches.filter((m) => targetIndexes.includes(m.index));\n }\n if (targetComponentUid) {\n affectedMatches = affectedMatches.filter((m) => m.componentUid === targetComponentUid);\n }\n\n if (affectedMatches.length > 0) {\n for (const match of affectedMatches) {\n let blockNewVal = value;\n if (regexObj && typeof match.value === 'string') {\n blockNewVal = match.value.replace(regexObj, value);\n }\n const hasChange = String(match.value ?? '') !== String(blockNewVal ?? '');\n if (hasChange) {\n willUpdateCount++;\n } else {\n unchangedCount++;\n }\n\n diffs.push({\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: `${entryLabel} [Block #${match.index} (${match.componentName})]`,\n attribute: `${rootKey}[#${match.index} ${match.componentName}].${parsed.subPath}`,\n oldValue: match.value ?? null,\n newValue: blockNewVal,\n oldDisplay: match.value !== undefined && match.value !== null && String(match.value).trim() !== '' ? String(match.value) : '(empty)',\n newDisplay: String(blockNewVal ?? ''),\n hasChange,\n status: hasChange ? 'will_update' : 'unchanged',\n message: hasChange ? 'Block value will be updated' : 'Block already has target value',\n });\n }\n continue;\n }\n }\n\n const currentVal = getDeepProperty(currentEntry, attribute);\n\n let newValue = value;\n if (regexObj && typeof currentVal === 'string') {\n newValue = currentVal.replace(regexObj, value);\n }\n\n const hasChange = String(currentVal ?? '') !== String(newValue ?? '');\n if (hasChange) {\n willUpdateCount++;\n } else {\n unchangedCount++;\n }\n\n diffs.push({\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: entryLabel,\n attribute,\n oldValue: currentVal ?? null,\n newValue,\n oldDisplay: currentVal !== undefined && currentVal !== null ? String(currentVal) : '(empty)',\n newDisplay: String(newValue ?? ''),\n hasChange,\n status: hasChange ? 'will_update' : 'unchanged',\n message: hasChange ? 'Value will be updated' : 'Already has target value',\n });\n continue;\n }\n\n if (attrDef?.type === 'relation') {\n const isMulti = attrDef.relation === 'oneToMany' || attrDef.relation === 'manyToMany';\n const currentRel = currentEntry?.[attribute];\n\n let oldDocIds: string[] = [];\n let oldDisplay = '';\n if (isMulti && Array.isArray(currentRel)) {\n oldDocIds = currentRel.map((r: any) => r.documentId).filter(Boolean);\n oldDisplay = currentRel.map((r: any) => r.name || r.title || r.email || r.documentId).join(', ') || '(empty)';\n } else if (currentRel) {\n oldDocIds = currentRel.documentId ? [currentRel.documentId] : [];\n oldDisplay = currentRel.name || currentRel.title || currentRel.email || currentRel.documentId || '(empty)';\n } else {\n oldDisplay = '(unlinked / none)';\n }\n\n let mode: 'set' | 'connect' | 'disconnect' | 'clear' = 'set';\n let targetDocIds: string[] = [];\n let newDisplay = '';\n\n if (value === '__clear__' || value === '') {\n mode = 'clear';\n newDisplay = '(cleared / unlinked)';\n } else {\n try {\n const parsed = JSON.parse(value);\n if (parsed && typeof parsed === 'object' && parsed.mode) {\n mode = parsed.mode;\n targetDocIds = Array.isArray(parsed.documentIds) ? parsed.documentIds : (parsed.documentId ? [parsed.documentId] : []);\n newDisplay = parsed.label || targetDocIds.join(', ') || `[${mode}]`;\n } else if (Array.isArray(parsed)) {\n targetDocIds = parsed;\n newDisplay = targetDocIds.join(', ');\n } else {\n targetDocIds = [value];\n newDisplay = value;\n }\n } catch {\n targetDocIds = [value];\n newDisplay = value;\n }\n }\n\n const hasChange = oldDisplay !== newDisplay;\n if (hasChange) {\n willUpdateCount++;\n } else {\n unchangedCount++;\n }\n\n diffs.push({\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: entryLabel,\n attribute,\n oldValue: { isRelation: true, documentIds: oldDocIds, display: oldDisplay },\n newValue: { isRelation: true, mode, documentIds: targetDocIds, display: newDisplay },\n oldDisplay,\n newDisplay,\n hasChange,\n status: hasChange ? 'will_update' : 'unchanged',\n message: hasChange ? `Relation will be modified (${mode})` : 'Relation already set to this target',\n });\n continue;\n }\n\n // Scalar attributes\n let newValue = value;\n const currentVal = currentEntry?.[attribute];\n\n if (regexObj && typeof currentVal === 'string') {\n newValue = currentVal.replace(regexObj, value);\n }\n\n const hasChange = String(currentVal ?? '') !== String(newValue ?? '');\n if (hasChange) {\n willUpdateCount++;\n } else {\n unchangedCount++;\n }\n\n diffs.push({\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: entryLabel,\n attribute,\n oldValue: currentVal ?? null,\n newValue,\n oldDisplay: currentVal !== undefined && currentVal !== null ? String(currentVal) : '(empty)',\n newDisplay: String(newValue ?? ''),\n hasChange,\n status: hasChange ? 'will_update' : 'unchanged',\n message: hasChange ? 'Value will be updated' : 'Already matches target value',\n });\n } catch (err: any) {\n skippedCount++;\n diffs.push({\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: `Entry #${target.documentId}`,\n attribute,\n oldValue: null,\n newValue: null,\n oldDisplay: '—',\n newDisplay: '—',\n hasChange: false,\n status: 'will_skip',\n message: `Error inspecting entry: ${err.message}`,\n });\n }\n }\n\n return {\n success: true,\n summary: {\n total: targets.length,\n willUpdate: willUpdateCount,\n unchanged: unchangedCount,\n skipped: skippedCount,\n },\n diffs,\n };\n },\n\n /**\n * Batch Update API with Maker-Checker and Off-Peak Scheduling:\n */\n async batchUpdate(\n {\n attribute,\n value,\n selectedEntries = [],\n selectedCollections = [],\n isRegex = false,\n regexPattern = '',\n executionMode = 'immediate',\n makerNotes = '',\n forceImmediate = false,\n publishOnApproval = true,\n publishStrategy = 'safe',\n unreviewedConsent = false,\n unreviewedCount = 0,\n }: {\n attribute: string;\n value: string;\n selectedEntries?: Array<{ uid: string; documentId: string; dynamicZoneIndexes?: number[]; targetComponentUid?: string }>;\n selectedCollections?: string[];\n isRegex?: boolean;\n regexPattern?: string;\n executionMode?: 'immediate' | 'queue_offpeak' | 'maker_checker';\n makerNotes?: string;\n forceImmediate?: boolean;\n publishOnApproval?: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n unreviewedCount?: number;\n },\n currentUser?: any\n ) {\n if (!attribute) {\n throw new Error('Attribute name is required.');\n }\n\n const executionConfig = getExecutionWindowConfig(strapi);\n const { isBusinessHours, policyMessage } = checkBusinessHours(executionConfig);\n\n // 1. Enterprise Maker-Checker Flow:\n if (executionMode === 'maker_checker') {\n const summary = await computeTargetsSummary(strapi, { selectedCollections, selectedEntries });\n if (summary.totalTargets === 0) {\n throw new Error('No collections or entries were selected for update.');\n }\n\n const batchId = `batch_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const batch: PendingBatch = {\n id: batchId,\n createdAt: new Date().toISOString(),\n createdBy: currentUser\n ? {\n id: currentUser.id,\n email: currentUser.email,\n firstname: currentUser.firstname,\n lastname: currentUser.lastname,\n username: currentUser.username,\n }\n : { email: 'admin@system.local' },\n payload: { attribute, value, selectedEntries, selectedCollections, isRegex, regexPattern, publishOnApproval, publishStrategy, unreviewedConsent, unreviewedCount },\n summary: {\n attribute,\n value,\n totalTargets: summary.totalTargets,\n collectionBreakdown: summary.collectionBreakdown,\n publishOnApproval,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n },\n status: 'pending_approval',\n executionMode: 'maker_checker',\n makerNotes,\n };\n\n pendingBatches.set(batchId, batch);\n batchJobsMap.set(batchId, {\n id: batchId,\n createdAt: batch.createdAt,\n createdBy: batch.createdBy,\n status: 'pending_approval',\n executionMode: 'maker_checker',\n attribute,\n value,\n totalTargets: summary.totalTargets,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: Boolean(publishOnApproval),\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n makerNotes,\n results: [],\n });\n\n return {\n success: true,\n pending: true,\n batchId,\n status: 'pending_approval',\n message: 'Batch submitted for Checker authorization (4-Eyes Maker-Checker Workflow).',\n batch,\n };\n }\n\n // 2. Off-Peak Queued Batch:\n if (executionMode === 'queue_offpeak') {\n const summary = await computeTargetsSummary(strapi, { selectedCollections, selectedEntries });\n if (summary.totalTargets === 0) {\n throw new Error('No collections or entries were selected for update.');\n }\n\n const batchId = `batch_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const batch: PendingBatch = {\n id: batchId,\n createdAt: new Date().toISOString(),\n createdBy: currentUser\n ? {\n id: currentUser.id,\n email: currentUser.email,\n firstname: currentUser.firstname,\n lastname: currentUser.lastname,\n username: currentUser.username,\n }\n : { email: 'admin@system.local' },\n payload: { attribute, value, selectedEntries, selectedCollections, isRegex, regexPattern, publishOnApproval, publishStrategy, unreviewedConsent, unreviewedCount },\n summary: {\n attribute,\n value,\n totalTargets: summary.totalTargets,\n collectionBreakdown: summary.collectionBreakdown,\n publishOnApproval,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n },\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n makerNotes,\n };\n\n pendingBatches.set(batchId, batch);\n batchJobsMap.set(batchId, {\n id: batchId,\n createdAt: batch.createdAt,\n createdBy: batch.createdBy,\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n attribute,\n value,\n totalTargets: summary.totalTargets,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: Boolean(publishOnApproval),\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n makerNotes,\n results: [],\n });\n\n return {\n success: true,\n pending: true,\n batchId,\n status: 'queued_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n message: `Batch queued for server off-peak maintenance window (${executionConfig.offPeakStartTime}).`,\n batch,\n };\n }\n\n // 3. Immediate execution request with Server Business Hours enforcement:\n if (executionConfig.enabled && executionConfig.autoQueueDuringBusinessHours && isBusinessHours && !forceImmediate) {\n const summary = await computeTargetsSummary(strapi, { selectedCollections, selectedEntries });\n if (summary.totalTargets === 0) {\n throw new Error('No collections or entries were selected for update.');\n }\n\n const batchId = `batch_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const batch: PendingBatch = {\n id: batchId,\n createdAt: new Date().toISOString(),\n createdBy: currentUser\n ? {\n id: currentUser.id,\n email: currentUser.email,\n firstname: currentUser.firstname,\n lastname: currentUser.lastname,\n username: currentUser.username,\n }\n : { email: 'admin@system.local' },\n payload: { attribute, value, selectedEntries, selectedCollections, isRegex, regexPattern, publishOnApproval, publishStrategy, unreviewedConsent, unreviewedCount },\n summary: {\n attribute,\n value,\n totalTargets: summary.totalTargets,\n collectionBreakdown: summary.collectionBreakdown,\n publishOnApproval,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n },\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n makerNotes: 'Automatically queued due to peak business hours restriction.',\n };\n\n pendingBatches.set(batchId, batch);\n batchJobsMap.set(batchId, {\n id: batchId,\n createdAt: batch.createdAt,\n createdBy: batch.createdBy,\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n attribute,\n value,\n totalTargets: summary.totalTargets,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: Boolean(publishOnApproval),\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n policyMessage,\n makerNotes: 'Automatically queued due to peak business hours restriction.',\n results: [],\n });\n\n return {\n success: true,\n pending: true,\n batchId,\n status: 'queued_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n message: policyMessage,\n batch,\n };\n }\n\n // 4. Immediate execution\n return await executeBatchInternal(\n strapi,\n { attribute, value, selectedEntries, selectedCollections, isRegex, regexPattern, publishOnApproval, publishStrategy, unreviewedConsent },\n currentUser\n );\n },\n\n /**\n * Bulk Publish selected entries or collections\n */\n async batchPublish(\n {\n selectedEntries = [],\n selectedCollections = [],\n executionMode = 'immediate',\n makerNotes = '',\n forceImmediate = false,\n unreviewedConsent = false,\n unreviewedCount = 0,\n }: {\n selectedEntries?: Array<{ uid: string; documentId: string }>;\n selectedCollections?: string[];\n executionMode?: 'immediate' | 'queue_offpeak' | 'maker_checker';\n makerNotes?: string;\n forceImmediate?: boolean;\n unreviewedConsent?: boolean;\n unreviewedCount?: number;\n },\n currentUser?: any\n ) {\n const executionConfig = getExecutionWindowConfig(strapi);\n const { isBusinessHours, policyMessage } = checkBusinessHours(executionConfig);\n\n // 1. Enterprise Maker-Checker Flow:\n if (executionMode === 'maker_checker') {\n const summary = await computeTargetsSummary(strapi, { selectedCollections, selectedEntries });\n if (summary.totalTargets === 0) {\n throw new Error('No collections or entries were selected to publish.');\n }\n\n const batchId = `batch_pub_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const batch: PendingBatch = {\n id: batchId,\n createdAt: new Date().toISOString(),\n createdBy: currentUser\n ? {\n id: currentUser.id,\n email: currentUser.email,\n firstname: currentUser.firstname,\n lastname: currentUser.lastname,\n username: currentUser.username,\n }\n : { email: 'admin@system.local' },\n payload: { action: 'publish', attribute: '(publish)', value: 'published', selectedEntries, selectedCollections, publishOnApproval: true, unreviewedConsent, unreviewedCount },\n summary: {\n attribute: '(publish)',\n value: 'published',\n totalTargets: summary.totalTargets,\n collectionBreakdown: summary.collectionBreakdown,\n publishOnApproval: true,\n unreviewedConsent,\n unreviewedCount,\n },\n status: 'pending_approval',\n executionMode: 'maker_checker',\n makerNotes,\n };\n\n pendingBatches.set(batchId, batch);\n batchJobsMap.set(batchId, {\n id: batchId,\n createdAt: batch.createdAt,\n createdBy: batch.createdBy,\n status: 'pending_approval',\n executionMode: 'maker_checker',\n attribute: '(publish)',\n value: 'published',\n totalTargets: summary.totalTargets,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: true,\n unreviewedConsent,\n unreviewedCount,\n makerNotes,\n results: [],\n });\n\n return {\n success: true,\n pending: true,\n batchId,\n status: 'pending_approval',\n message: 'Bulk publish batch submitted for Checker authorization (4-Eyes Maker-Checker Workflow).',\n batch,\n };\n }\n\n // 2. Off-Peak Queued Batch:\n if (executionMode === 'queue_offpeak') {\n const summary = await computeTargetsSummary(strapi, { selectedCollections, selectedEntries });\n if (summary.totalTargets === 0) {\n throw new Error('No collections or entries were selected to publish.');\n }\n\n const batchId = `batch_pub_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const batch: PendingBatch = {\n id: batchId,\n createdAt: new Date().toISOString(),\n createdBy: currentUser\n ? {\n id: currentUser.id,\n email: currentUser.email,\n firstname: currentUser.firstname,\n lastname: currentUser.lastname,\n username: currentUser.username,\n }\n : { email: 'admin@system.local' },\n payload: { action: 'publish', attribute: '(publish)', value: 'published', selectedEntries, selectedCollections, publishOnApproval: true, unreviewedConsent, unreviewedCount },\n summary: {\n attribute: '(publish)',\n value: 'published',\n totalTargets: summary.totalTargets,\n collectionBreakdown: summary.collectionBreakdown,\n publishOnApproval: true,\n unreviewedConsent,\n unreviewedCount,\n },\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n makerNotes,\n };\n\n pendingBatches.set(batchId, batch);\n batchJobsMap.set(batchId, {\n id: batchId,\n createdAt: batch.createdAt,\n createdBy: batch.createdBy,\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n attribute: '(publish)',\n value: 'published',\n totalTargets: summary.totalTargets,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: true,\n unreviewedConsent,\n unreviewedCount,\n makerNotes,\n results: [],\n });\n\n return {\n success: true,\n pending: true,\n batchId,\n status: 'queued_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n message: `Bulk publish batch queued for server off-peak maintenance window (${executionConfig.offPeakStartTime}).`,\n batch,\n };\n }\n\n // 3. Peak hours auto-queue check\n if (executionConfig.enabled && executionConfig.autoQueueDuringBusinessHours && isBusinessHours && !forceImmediate) {\n const summary = await computeTargetsSummary(strapi, { selectedCollections, selectedEntries });\n if (summary.totalTargets === 0) {\n throw new Error('No collections or entries were selected to publish.');\n }\n\n const batchId = `batch_pub_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const batch: PendingBatch = {\n id: batchId,\n createdAt: new Date().toISOString(),\n createdBy: currentUser\n ? {\n id: currentUser.id,\n email: currentUser.email,\n firstname: currentUser.firstname,\n lastname: currentUser.lastname,\n username: currentUser.username,\n }\n : { email: 'admin@system.local' },\n payload: { action: 'publish', attribute: '(publish)', value: 'published', selectedEntries, selectedCollections, publishOnApproval: true, unreviewedConsent, unreviewedCount },\n summary: {\n attribute: '(publish)',\n value: 'published',\n totalTargets: summary.totalTargets,\n collectionBreakdown: summary.collectionBreakdown,\n publishOnApproval: true,\n unreviewedConsent,\n unreviewedCount,\n },\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n makerNotes: 'Automatically queued due to peak business hours restriction.',\n };\n\n pendingBatches.set(batchId, batch);\n batchJobsMap.set(batchId, {\n id: batchId,\n createdAt: batch.createdAt,\n createdBy: batch.createdBy,\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n attribute: '(publish)',\n value: 'published',\n totalTargets: summary.totalTargets,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: true,\n unreviewedConsent,\n unreviewedCount,\n policyMessage,\n makerNotes: 'Automatically queued due to peak business hours restriction.',\n results: [],\n });\n\n return {\n success: true,\n pending: true,\n batchId,\n status: 'queued_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n message: policyMessage,\n batch,\n };\n }\n\n // 4. Immediate execution\n return await executePublishBatchInternal(\n strapi,\n { selectedEntries, selectedCollections, unreviewedConsent },\n currentUser\n );\n },\n\n /**\n * Get Pending & Queued Batches\n */\n getPendingBatches() {\n const executionConfig = getExecutionWindowConfig(strapi);\n const windowStatus = checkBusinessHours(executionConfig);\n const batches = Array.from(pendingBatches.values()).sort(\n (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()\n );\n\n return {\n success: true,\n batches,\n executionWindow: {\n ...executionConfig,\n ...windowStatus,\n },\n };\n },\n\n /**\n * Checker Approves Batch\n */\n async approveBatch(batchId: string, checkerUser: any, options: { executeImmediately?: boolean } = { executeImmediately: true }) {\n const batch = pendingBatches.get(batchId);\n if (!batch) {\n throw new Error(`Pending batch ${batchId} not found.`);\n }\n if (batch.status !== 'pending_approval') {\n throw new Error(`Batch ${batchId} is not pending approval (current status: ${batch.status}).`);\n }\n\n batch.approval = {\n checkerUser: checkerUser\n ? {\n id: checkerUser.id,\n email: checkerUser.email,\n firstname: checkerUser.firstname,\n lastname: checkerUser.lastname,\n username: checkerUser.username,\n }\n : { email: 'checker@system.local' },\n decisionDate: new Date().toISOString(),\n };\n\n const config = getExecutionWindowConfig(strapi);\n const { isBusinessHours } = checkBusinessHours(config);\n\n if (options.executeImmediately || !isBusinessHours) {\n batch.status = 'approved';\n const result = await executeBatchByPayload(strapi, batch, checkerUser);\n batch.status = 'executed';\n batch.executionResult = result;\n return {\n success: true,\n batchId,\n status: 'executed',\n message: 'Batch approved and executed successfully by Checker.',\n batch,\n result,\n };\n } else {\n batch.status = 'approved';\n return {\n success: true,\n batchId,\n status: 'approved',\n message: `Batch approved by Checker. Queued for execution during off-peak window (${config.offPeakStartTime}).`,\n batch,\n };\n }\n },\n\n /**\n * Checker Rejects Batch\n */\n rejectBatch(batchId: string, checkerUser: any, reason: string = 'Rejected by Checker') {\n const batch = pendingBatches.get(batchId);\n if (!batch) {\n throw new Error(`Pending batch ${batchId} not found.`);\n }\n batch.status = 'rejected';\n batch.approval = {\n checkerUser: checkerUser\n ? {\n id: checkerUser.id,\n email: checkerUser.email,\n firstname: checkerUser.firstname,\n lastname: checkerUser.lastname,\n username: checkerUser.username,\n }\n : { email: 'checker@system.local' },\n decisionDate: new Date().toISOString(),\n rejectionReason: reason,\n };\n\n return {\n success: true,\n batchId,\n status: 'rejected',\n message: `Batch rejected by Checker: ${reason}`,\n batch,\n };\n },\n\n /**\n * Run Batch Immediately\n */\n async executeNow(batchId: string, currentUser: any) {\n const batch = pendingBatches.get(batchId);\n if (!batch) {\n throw new Error(`Pending batch ${batchId} not found.`);\n }\n if (batch.status === 'executed') {\n throw new Error(`Batch ${batchId} has already been executed.`);\n }\n\n const result = await executeBatchByPayload(strapi, batch, currentUser);\n batch.status = 'executed';\n batch.executionResult = result;\n\n return {\n success: true,\n batchId,\n status: 'executed',\n message: 'Batch executed immediately.',\n batch,\n result,\n };\n },\n\n /**\n * Get real-time or historical processing status of a batch job\n */\n async getBatchStatus(batchId: string) {\n if (!batchId) throw new Error('batchId is required');\n\n let job = batchJobsMap.get(batchId);\n if (job) {\n return { success: true, batch: job };\n }\n\n const pending = pendingBatches.get(batchId);\n if (pending) {\n const pendingJob: BatchJobState = {\n id: pending.id,\n createdAt: pending.createdAt,\n createdBy: pending.createdBy,\n status: pending.status as any,\n executionMode: pending.executionMode,\n scheduledFor: pending.scheduledFor,\n attribute: pending.payload.attribute,\n value: pending.payload.value,\n totalTargets: pending.summary.totalTargets,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: Boolean(pending.payload.publishOnApproval),\n policyMessage: pending.makerNotes,\n results: [],\n };\n return { success: true, batch: pendingJob };\n }\n\n // Fallback: Query historical audit log\n try {\n const auditService = strapi.plugin('bulk-updater').service('audit');\n const historyData = await auditService.getHistory();\n const records = Array.isArray(historyData?.history) ? historyData.history : [];\n const found = records.find((r: any) => r.batchId === batchId);\n\n if (found) {\n const total = found.totalTargets || (found.updatedCount + found.skippedCount) || 1;\n const historicalJob: BatchJobState = {\n id: found.batchId,\n createdAt: found.executedAt || found.createdAt || new Date().toISOString(),\n startedAt: found.executedAt || found.createdAt,\n completedAt: found.executedAt || found.createdAt,\n createdBy: {\n email: found.userEmail || 'admin@strapi.io',\n firstname: found.userName || 'Admin',\n },\n status: found.isRolledBack ? 'failed' : 'successful',\n executionMode: 'immediate',\n attribute: found.attribute,\n value: found.value,\n totalTargets: total,\n processedCount: total,\n updatedCount: found.updatedCount || 0,\n skippedCount: found.skippedCount || 0,\n failedCount: 0,\n isLive: !found.isRolledBack && found.updatedCount > 0,\n publishOnApproval: true,\n results: (found.diffs || []).map((d: any) => ({\n uid: d.uid,\n collectionName: d.collectionName || d.uid,\n documentId: d.documentId,\n label: d.label || `Entry #${d.documentId}`,\n attribute: d.attribute || found.attribute,\n oldValue: d.oldValue,\n newValue: d.newValue,\n status: d.status || 'updated',\n isLive: !found.isRolledBack,\n message: d.message || 'Updated via bulk update',\n })),\n };\n batchJobsMap.set(batchId, historicalJob);\n return { success: true, batch: historicalJob };\n }\n } catch (err) {\n // Fallthrough\n }\n\n throw new Error(`Batch with ID \"${batchId}\" was not found.`);\n },\n\n /**\n * Downloadable execution report (CSV or JSON)\n */\n async getBatchReport(batchId: string, format: string = 'csv') {\n const statusRes = await this.getBatchStatus(batchId);\n const batch = statusRes.batch;\n\n function escapeCsvVal(val: any): string {\n if (val === null || val === undefined) return '';\n let str = typeof val === 'object' ? JSON.stringify(val) : String(val);\n str = str.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\n if (/^[=+@-]$/.test(str.charAt(0))) {\n str = `'${str}`;\n }\n if (str.includes(',') || str.includes('\"') || str.includes('\\n')) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n return str;\n }\n\n const headers = [\n 'Batch ID',\n 'Collection UID',\n 'Collection Name',\n 'Document ID',\n 'Record Title / Identifier',\n 'Attribute Name',\n 'Previous Value',\n 'New Live Value',\n 'Processing Status',\n 'Live On Server',\n 'Details / Message',\n 'Executed At',\n 'Operator',\n ];\n\n const rows: string[] = [headers.join(',')];\n\n for (const item of batch.results || []) {\n const row = [\n escapeCsvVal(batch.id),\n escapeCsvVal(item.uid),\n escapeCsvVal(item.collectionName),\n escapeCsvVal(item.documentId),\n escapeCsvVal(item.label),\n escapeCsvVal(item.attribute),\n escapeCsvVal(item.oldValue),\n escapeCsvVal(item.newValue),\n escapeCsvVal(item.status === 'updated' ? 'Updated' : item.status === 'error' ? 'Failed' : 'Skipped'),\n escapeCsvVal(item.isLive ? 'YES (Live on Site)' : 'NO'),\n escapeCsvVal(item.message),\n escapeCsvVal(batch.completedAt || batch.createdAt),\n escapeCsvVal(batch.createdBy?.email || 'admin@strapi.io'),\n ];\n rows.push(row.join(','));\n }\n\n const safeBatchId = batch.id.replace(/[^a-zA-Z0-9_-]/g, '_');\n const filename = `bulk_update_report_${safeBatchId}_${new Date().toISOString().slice(0, 10)}.csv`;\n\n return {\n success: true,\n filename,\n csvContent: '\\uFEFF' + rows.join('\\r\\n') + '\\r\\n',\n summary: {\n batchId: batch.id,\n status: batch.status,\n isLive: batch.isLive,\n totalTargets: batch.totalTargets,\n updatedCount: batch.updatedCount,\n skippedCount: batch.skippedCount,\n failedCount: batch.failedCount,\n executedAt: batch.completedAt || batch.createdAt,\n operator: batch.createdBy?.email || 'admin@strapi.io',\n },\n batch,\n };\n },\n\n /**\n * Inspect batch changes item-by-item for Maker-Checker 4-Eyes review\n */\n async getPendingBatchDiffs(batchId: string) {\n if (!batchId) throw new Error('batchId is required');\n const batch = pendingBatches.get(batchId);\n if (!batch) {\n throw new Error(`Pending batch \"${batchId}\" not found.`);\n }\n\n let previewRes: any = null;\n\n if (batch.payload?.action === 'csv_import' || batch.id.startsWith('csv_')) {\n const csvService = strapi.plugin('bulk-updater').service('csv');\n previewRes = await csvService.previewCsvBatch(\n batch.payload.uid,\n batch.payload.rows || [],\n batch.payload.options || {}\n );\n } else if (batch.payload?.action === 'publish') {\n const selectedEntries = batch.payload.selectedEntries || [];\n const selectedCollections = batch.payload.selectedCollections || [];\n const targetsMap = new Map<string, { uid: string; documentId: string }>();\n\n for (const colUid of selectedCollections) {\n if (!strapi.contentTypes[colUid]) continue;\n const entries = await (strapi.documents(colUid as any) as any).findMany();\n for (const entry of (entries || []) as any[]) {\n targetsMap.set(`${colUid}@@@${entry.documentId}`, { uid: colUid, documentId: entry.documentId });\n }\n }\n\n for (const item of selectedEntries) {\n if (!item.uid || !item.documentId) continue;\n targetsMap.set(`${item.uid}@@@${item.documentId}`, { uid: item.uid, documentId: item.documentId });\n }\n\n const diffs: any[] = [];\n let willUpdate = 0;\n let unchanged = 0;\n\n for (const target of targetsMap.values()) {\n const ct = strapi.contentTypes[target.uid];\n const displayName = ct?.info?.displayName || target.uid;\n try {\n const doc: any = await (strapi.documents(target.uid as any) as any).findOne({\n documentId: target.documentId,\n });\n const label = doc ? doc.title || doc.name || doc.slug || doc.documentId : target.documentId;\n const isLive = Boolean(doc?.publishedAt) && doc?.status !== 'modified';\n const currentStatus = isLive ? 'published' : (doc?.status === 'modified' ? 'modified draft' : 'draft');\n const hasChange = !isLive;\n if (hasChange) willUpdate++;\n else unchanged++;\n\n diffs.push({\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label,\n attribute: 'status',\n oldValue: currentStatus,\n newValue: 'published',\n oldDisplay: currentStatus,\n newDisplay: 'published live',\n hasChange,\n status: hasChange ? 'will_update' : 'unchanged',\n action: 'publish',\n message: hasChange ? 'Record will be published live' : 'Already published live',\n });\n } catch (err: any) {\n diffs.push({\n uid: target.uid,\n collectionName: displayName,\n documentId: target.documentId,\n label: target.documentId,\n attribute: 'status',\n oldValue: null,\n newValue: null,\n oldDisplay: '—',\n newDisplay: '—',\n hasChange: false,\n status: 'will_skip',\n action: 'skip',\n message: `Error inspecting document: ${err.message}`,\n });\n }\n }\n\n previewRes = {\n success: true,\n summary: {\n total: targetsMap.size,\n willUpdate,\n willCreate: 0,\n unchanged,\n skipped: 0,\n },\n diffs,\n };\n } else {\n // Standard Bulk Update\n const preview = await this.previewBatch({\n attribute: batch.payload.attribute,\n value: batch.payload.value,\n selectedEntries: batch.payload.selectedEntries,\n selectedCollections: batch.payload.selectedCollections,\n isRegex: batch.payload.isRegex,\n regexPattern: batch.payload.regexPattern,\n });\n\n previewRes = {\n success: true,\n summary: {\n total: preview.summary?.total ?? 0,\n willUpdate: preview.summary?.willUpdate ?? 0,\n willCreate: 0,\n unchanged: preview.summary?.unchanged ?? 0,\n skipped: preview.summary?.skipped ?? 0,\n },\n diffs: (preview.diffs || []).map((d: any) => ({\n ...d,\n action: 'update',\n })),\n };\n }\n\n return {\n success: true,\n batchId: batch.id,\n createdAt: batch.createdAt,\n createdBy: batch.createdBy,\n makerNotes: batch.makerNotes,\n batchSummary: batch.summary,\n payload: {\n action: batch.payload?.action || 'bulk_update',\n attribute: batch.payload?.attribute,\n value: batch.payload?.value,\n publishOnApproval: batch.summary?.publishOnApproval,\n publishStrategy: batch.summary?.publishStrategy,\n },\n summary: previewRes.summary,\n diffs: previewRes.diffs,\n };\n },\n\n /**\n * Export batch diffs to CSV for offline audit review\n */\n async getPendingBatchDiffsCsv(batchId: string) {\n const data = await this.getPendingBatchDiffs(batchId);\n\n function escapeVal(val: any): string {\n if (val === null || val === undefined) return '';\n let str = typeof val === 'object' ? JSON.stringify(val) : String(val);\n str = str.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\n if (/^[=+@-]$/.test(str.charAt(0))) {\n str = `'${str}`;\n }\n if (str.includes(',') || str.includes('\"') || str.includes('\\n')) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n return str;\n }\n\n const headers = [\n 'Batch ID',\n 'Action',\n 'Collection UID',\n 'Collection Name',\n 'Document ID',\n 'Record Identifier',\n 'Attribute Name',\n 'Original Value (Before)',\n 'Proposed Value (After)',\n 'Change Status',\n 'Details / Message',\n ];\n\n const rows: string[] = [headers.join(',')];\n\n for (const diff of data.diffs || []) {\n const row = [\n escapeVal(data.batchId),\n escapeVal(diff.action || 'update'),\n escapeVal(diff.uid),\n escapeVal(diff.collectionName),\n escapeVal(diff.documentId),\n escapeVal(diff.label),\n escapeVal(diff.attribute),\n escapeVal(diff.oldDisplay ?? diff.oldValue),\n escapeVal(diff.newDisplay ?? diff.newValue),\n escapeVal(\n diff.status === 'will_update'\n ? 'Will Update'\n : diff.status === 'will_create'\n ? 'Will Create'\n : diff.status === 'unchanged'\n ? 'Unchanged'\n : 'Skipped'\n ),\n escapeVal(diff.message),\n ];\n rows.push(row.join(','));\n }\n\n const safeBatchId = batchId.replace(/[^a-zA-Z0-9_-]/g, '_');\n const filename = `pending_batch_review_${safeBatchId}_${new Date().toISOString().slice(0, 10)}.csv`;\n\n return {\n success: true,\n filename,\n csvContent: '\\uFEFF' + rows.join('\\r\\n') + '\\r\\n',\n count: data.diffs?.length || 0,\n };\n },\n\n /**\n * Get recent batch jobs for the processing dashboard\n */\n async getRecentBatches() {\n const mergedMap = new Map<string, any>();\n\n // 1. From in-memory batchJobsMap\n for (const [id, job] of batchJobsMap.entries()) {\n mergedMap.set(id, {\n id: job.id,\n createdAt: job.createdAt,\n completedAt: job.completedAt,\n status: job.status,\n isLive: job.isLive,\n executionMode: job.executionMode,\n attribute: job.attribute,\n value: job.value,\n totalTargets: job.totalTargets,\n updatedCount: job.updatedCount,\n skippedCount: job.skippedCount,\n failedCount: job.failedCount,\n operator: job.createdBy?.email || 'admin@strapi.io',\n });\n }\n\n // 2. From pendingBatches\n for (const [id, p] of pendingBatches.entries()) {\n if (!mergedMap.has(id)) {\n mergedMap.set(id, {\n id: p.id,\n createdAt: p.createdAt,\n status: p.status,\n isLive: false,\n executionMode: p.executionMode,\n attribute: p.payload.attribute,\n value: p.payload.value,\n totalTargets: p.summary.totalTargets,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n operator: p.createdBy?.email || 'admin@strapi.io',\n });\n }\n }\n\n // 3. From audit history\n try {\n const auditService = strapi.plugin('bulk-updater').service('audit');\n const historyData = await auditService.getHistory();\n const records = Array.isArray(historyData?.history) ? historyData.history : [];\n for (const r of records) {\n if (!mergedMap.has(r.batchId)) {\n mergedMap.set(r.batchId, {\n id: r.batchId,\n createdAt: r.executedAt || r.createdAt,\n completedAt: r.executedAt,\n status: r.isRolledBack ? 'failed' : 'successful',\n isLive: !r.isRolledBack && r.updatedCount > 0,\n executionMode: 'immediate',\n attribute: r.attribute,\n value: r.value,\n totalTargets: r.totalTargets || (r.updatedCount + r.skippedCount) || 1,\n updatedCount: r.updatedCount || 0,\n skippedCount: r.skippedCount || 0,\n failedCount: 0,\n operator: r.userEmail || 'admin@strapi.io',\n });\n }\n }\n } catch {\n // Ignore\n }\n\n const batches = Array.from(mergedMap.values()).sort(\n (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()\n );\n\n return {\n success: true,\n batches: batches.slice(0, 50),\n };\n },\n\n invalidateCache(uid?: string) {\n if (uid) {\n invalidateCollectionCache(uid);\n } else {\n queryCache.clear();\n modelsCache.clear();\n staticSchemaCache = null;\n }\n },\n\n invalidateCollectionCache(uid: string) {\n invalidateCollectionCache(uid);\n },\n\n registerPendingBatch(batch: PendingBatch, jobState?: BatchJobState) {\n pendingBatches.set(batch.id, batch);\n if (jobState) {\n batchJobsMap.set(batch.id, jobState);\n }\n return batch;\n },\n\n getExecutionWindowConfig() {\n return getExecutionWindowConfig(strapi);\n },\n\n checkBusinessHours(config?: ExecutionWindowConfig) {\n const cfg = config || getExecutionWindowConfig(strapi);\n return checkBusinessHours(cfg);\n },\n };\n};\n","import type { Core } from '@strapi/strapi';\nimport { recordContentHistoryVersion } from './content-history';\nimport {\n setDeepProperty,\n buildDeepPopulate,\n parseDynamicZonePath,\n isDeepComponentField,\n} from './bulk-updater';\n\nexport interface AuditConfig {\n enabled: boolean;\n mode?: 'custom' | 'default' | 'enterprise_native' | 'store' | 'disabled';\n contentType?: string;\n fields?: Record<string, string>;\n isEnterpriseNativeAvailable?: boolean;\n error?: string;\n}\n\nconst DEFAULT_FIELDS: Record<string, string> = {\n batchId: 'batchId',\n attribute: 'attribute',\n value: 'value',\n userEmail: 'userEmail',\n userName: 'userName',\n updatedCount: 'updatedCount',\n skippedCount: 'skippedCount',\n totalTargets: 'totalTargets',\n diffs: 'diffs',\n isRolledBack: 'isRolledBack',\n rolledBackAt: 'rolledBackAt',\n rolledBackBy: 'rolledBackBy',\n executedAt: 'executedAt',\n};\n\nconst DEFAULT_CANDIDATE_TYPES = [\n 'plugin::bulk-updater.audit-log',\n 'api::audit-log.audit-log',\n 'api::audit.audit',\n 'api::bulk-audit-log.bulk-audit-log',\n];\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => ({\n /**\n * Detects whether Strapi Enterprise Native Audit Log service is available.\n */\n getEnterpriseAuditService() {\n try {\n const svc =\n (strapi as any).service?.('admin::audit-logs') ||\n (strapi as any).admin?.services?.['audit-logs'];\n return svc || null;\n } catch {\n return null;\n }\n },\n\n /**\n * Resolves the audit configuration:\n * 1. Explicit consumer custom schema (full declarative control)\n * 2. Zero-config convention auto-detection (api::audit-log.audit-log)\n * 3. Strapi Enterprise native audit log bridge\n * 4. Zero-config plugin core store (works out of the box in 100% of Strapi installations)\n */\n getAuditConfig(): AuditConfig {\n const rawConfig = strapi.config.get('plugin::bulk-updater.audit') as any;\n const eeService = this.getEnterpriseAuditService();\n const isEnterpriseNativeAvailable = Boolean(\n eeService && typeof eeService.save === 'function'\n );\n\n // If consumer explicitly disabled audit\n if (rawConfig && rawConfig.enabled === false) {\n return {\n enabled: false,\n mode: 'disabled',\n isEnterpriseNativeAvailable,\n };\n }\n\n // Tier 1: Explicit consumer custom schema\n if (rawConfig?.contentType) {\n const { contentType, fields } = rawConfig;\n const schema = strapi.contentTypes[contentType];\n if (!schema) {\n return {\n enabled: false,\n mode: 'disabled',\n isEnterpriseNativeAvailable,\n error: `Declared audit contentType \"${contentType}\" does not exist in Strapi schema registry.`,\n };\n }\n\n // Check fields or fallback to DEFAULT_FIELDS\n const resolvedFields = { ...DEFAULT_FIELDS, ...(fields || {}) };\n return {\n enabled: true,\n mode: 'custom',\n contentType,\n fields: resolvedFields,\n isEnterpriseNativeAvailable,\n };\n }\n\n // Tier 2: Zero-config auto-discovery of default audit collection\n for (const candidate of DEFAULT_CANDIDATE_TYPES) {\n if (strapi.contentTypes[candidate]) {\n return {\n enabled: true,\n mode: 'default',\n contentType: candidate,\n fields: DEFAULT_FIELDS,\n isEnterpriseNativeAvailable,\n };\n }\n }\n\n // Tier 3: Strapi Enterprise native audit logs\n if (isEnterpriseNativeAvailable) {\n return {\n enabled: true,\n mode: 'enterprise_native',\n isEnterpriseNativeAvailable: true,\n };\n }\n\n // Tier 4: Zero-config core store fallback (always available in all Strapi installations)\n return {\n enabled: true,\n mode: 'store',\n isEnterpriseNativeAvailable: false,\n };\n },\n\n /**\n * Checks whether audit logging is enabled.\n */\n isAuditEnabled(): boolean {\n const config = this.getAuditConfig();\n return Boolean(config && config.enabled);\n },\n\n /**\n * Convenience alias to log an operation into the audit trail.\n */\n async logOperation(data: {\n batchId: string;\n attribute: string;\n value: string;\n userEmail?: string;\n userName?: string;\n updatedCount: number;\n skippedCount: number;\n totalTargets: number;\n diffs?: any[];\n }) {\n return this.recordBatch(\n {\n batchId: data.batchId,\n attribute: data.attribute,\n value: data.value,\n updatedCount: data.updatedCount,\n skippedCount: data.skippedCount,\n totalTargets: data.totalTargets,\n },\n data.diffs || [],\n {\n email: data.userEmail,\n firstname: data.userName,\n }\n );\n },\n\n /**\n * Optionally writes an audit event directly to Strapi Enterprise's native Audit Logs table.\n */\n async recordToEnterpriseNative(\n action: string,\n payload: Record<string, any>,\n user?: any\n ) {\n try {\n const eeService = this.getEnterpriseAuditService();\n if (eeService && typeof eeService.save === 'function') {\n await eeService.save({\n action,\n date: new Date(),\n userId: user?.id,\n payload,\n });\n strapi.log.info(\n `[bulk-updater] Successfully dispatched event to Strapi Enterprise Audit Log: ${action}`\n );\n }\n } catch (err: any) {\n strapi.log.warn(\n `[bulk-updater] Note: Could not dispatch to Strapi Enterprise native audit log: ${err.message}`\n );\n }\n },\n\n /**\n * Records a batch execution:\n * - Dispatches to Strapi Enterprise native audit log if available\n * - Records to consumer or auto-detected collection type for one-click rollback\n */\n async recordBatch(\n batchSummary: {\n batchId: string;\n attribute: string;\n value: string;\n updatedCount: number;\n skippedCount: number;\n totalTargets: number;\n publishOnApproval?: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n },\n results: any[],\n user?: any\n ) {\n const config = this.getAuditConfig();\n\n // 1. Always attempt Strapi Enterprise native logging if available\n await this.recordToEnterpriseNative(\n 'bulk-updater.batch-update',\n {\n batchId: batchSummary.batchId,\n attribute: batchSummary.attribute,\n value: batchSummary.value,\n updatedCount: batchSummary.updatedCount,\n skippedCount: batchSummary.skippedCount,\n totalTargets: batchSummary.totalTargets,\n publishStrategy: batchSummary.publishStrategy,\n unreviewedConsent: batchSummary.unreviewedConsent,\n },\n user\n );\n\n // 2. Persist to rollback-capable storage\n if (!config.enabled) {\n return null;\n }\n\n if (config.mode === 'store') {\n try {\n const store = strapi.store({ type: 'plugin', name: 'bulk-updater', key: 'audit-history' });\n const stored = (await store.get({})) || { history: [] };\n const history = Array.isArray(stored.history) ? stored.history : [];\n\n const newRecord = {\n id: batchSummary.batchId,\n documentId: batchSummary.batchId,\n batchId: batchSummary.batchId,\n attribute: batchSummary.attribute,\n value: batchSummary.value,\n userEmail: user?.email || 'admin@strapi.io',\n userName: user?.firstname\n ? `${user.firstname} ${user.lastname || ''}`.trim()\n : user?.email || 'Admin',\n updatedCount: batchSummary.updatedCount,\n skippedCount: batchSummary.skippedCount,\n totalTargets: batchSummary.totalTargets,\n publishOnApproval: batchSummary.publishOnApproval,\n publishStrategy: batchSummary.publishStrategy,\n unreviewedConsent: batchSummary.unreviewedConsent,\n diffs: results,\n isRolledBack: false,\n rolledBackAt: null,\n rolledBackBy: null,\n executedAt: new Date().toISOString(),\n };\n\n const updatedHistory = [newRecord, ...history].slice(0, 200);\n await store.set({ value: { history: updatedHistory } });\n return newRecord;\n } catch (err: any) {\n strapi.log.error(`[bulk-updater] Failed to record audit log in core store: ${err.message}`);\n return null;\n }\n }\n\n if (!config.contentType || !config.fields) {\n return null;\n }\n\n const f = config.fields;\n const mappedData: any = {};\n\n if (f.batchId) mappedData[f.batchId] = batchSummary.batchId;\n if (f.attribute) mappedData[f.attribute] = batchSummary.attribute;\n if (f.value) mappedData[f.value] = batchSummary.value;\n if (f.userEmail) mappedData[f.userEmail] = user?.email || 'admin@strapi.io';\n if (f.userName) {\n mappedData[f.userName] = user?.firstname\n ? `${user.firstname} ${user.lastname || ''}`.trim()\n : user?.email || 'Admin';\n }\n if (f.updatedCount) mappedData[f.updatedCount] = batchSummary.updatedCount;\n if (f.skippedCount) mappedData[f.skippedCount] = batchSummary.skippedCount;\n if (f.totalTargets) mappedData[f.totalTargets] = batchSummary.totalTargets;\n if (f.diffs) mappedData[f.diffs] = results;\n if (f.isRolledBack) mappedData[f.isRolledBack] = false;\n if (f.executedAt) mappedData[f.executedAt] = new Date().toISOString();\n\n try {\n const created = await strapi.documents(config.contentType as any).create({\n data: mappedData,\n });\n return created;\n } catch (err: any) {\n strapi.log.error(`[bulk-updater] Failed to record audit log: ${err.message}`);\n return null;\n }\n },\n\n /**\n * Fetches audit history for the UI\n */\n async getHistory() {\n const config = this.getAuditConfig();\n\n if (config.mode === 'enterprise_native' && !config.contentType) {\n return {\n enabled: true,\n mode: 'enterprise_native',\n message:\n 'Strapi Enterprise Native Audit Logs active. Batch events are recorded directly to Strapi Settings > Audit Logs. (To enable one-click document rollback, declare or add an audit-log collection).',\n history: [],\n };\n }\n\n if (config.mode === 'store') {\n try {\n const store = strapi.store({ type: 'plugin', name: 'bulk-updater', key: 'audit-history' });\n const stored = (await store.get({})) || { history: [] };\n const history = Array.isArray(stored.history) ? stored.history : [];\n\n return {\n enabled: true,\n mode: 'store',\n isEnterpriseNativeAvailable: config.isEnterpriseNativeAvailable,\n history,\n };\n } catch (err: any) {\n return {\n enabled: false,\n message: `Failed to read audit history from core store: ${err.message}`,\n history: [],\n };\n }\n }\n\n if (!config.enabled || !config.contentType || !config.fields) {\n return {\n enabled: false,\n message:\n config.error ||\n 'Audit trail is disabled. To enable audit logs & rollback, declare an audit schema in config/plugins.ts or create api::audit-log.audit-log.',\n history: [],\n };\n }\n\n try {\n const records: any[] = await strapi.documents(config.contentType as any).findMany({\n sort: { createdAt: 'desc' } as any,\n });\n\n const f = config.fields;\n const normalized = (records || []).map((r: any) => ({\n id: r.id,\n documentId: r.documentId,\n batchId: r[f.batchId] || r.documentId,\n attribute: r[f.attribute],\n value: r[f.value],\n userEmail: r[f.userEmail] || 'admin@strapi.io',\n userName: r[f.userName] || 'Admin',\n updatedCount: r[f.updatedCount] || 0,\n skippedCount: r[f.skippedCount] || 0,\n totalTargets: r[f.totalTargets] || 0,\n diffs: typeof r[f.diffs] === 'string' ? JSON.parse(r[f.diffs]) : r[f.diffs] || [],\n isRolledBack: Boolean(r[f.isRolledBack]),\n rolledBackAt: r[f.rolledBackAt] || null,\n rolledBackBy: r[f.rolledBackBy] || null,\n executedAt: r[f.executedAt] || r.createdAt,\n }));\n\n return {\n enabled: true,\n mode: config.mode,\n contentType: config.contentType,\n isEnterpriseNativeAvailable: config.isEnterpriseNativeAvailable,\n history: normalized,\n };\n } catch (err: any) {\n return {\n enabled: false,\n message: `Failed to read audit history: ${err.message}`,\n history: [],\n };\n }\n },\n\n /**\n * Helper to revert diff items back to original values\n */\n async revertDiffItems(diffs: any[], userId?: any) {\n let revertedCount = 0;\n const rollbackDetails = [];\n\n for (const item of diffs) {\n if (item.status === 'updated' && item.uid && item.documentId && item.attribute) {\n try {\n const ct = strapi.contentTypes[item.uid];\n if (!ct) {\n throw new Error(`Content type \"${item.uid}\" does not exist in schema.`);\n }\n\n const isRel = item.oldValue && typeof item.oldValue === 'object' && item.oldValue.isRelation;\n let rollbackPayload: any;\n\n if (isRel) {\n const oldDocIds = Array.isArray(item.oldValue.documentIds) ? item.oldValue.documentIds : [];\n rollbackPayload = { set: oldDocIds };\n } else {\n rollbackPayload = item.oldValue ?? null;\n }\n\n const parsed = parseDynamicZonePath(item.attribute);\n const rootKey = parsed.rootKey;\n const rootAttrDef = ct.attributes?.[rootKey];\n const isComponent = rootAttrDef?.type === 'component';\n const isDynamicZone = rootAttrDef?.type === 'dynamiczone';\n const isNested =\n item.attribute.includes('.') ||\n item.attribute.includes('[') ||\n isComponent ||\n isDynamicZone ||\n isDeepComponentField(ct, strapi.components, item.attribute);\n\n let wasPublished = false;\n\n if (isNested && (isComponent || isDynamicZone || rootAttrDef)) {\n // Retrieve current document with recursive deep populate to preserve all sibling fields, components, media, and relations\n const populateOption = buildDeepPopulate(ct.attributes, strapi.components);\n const findOneArgs: any = { documentId: item.documentId };\n if (populateOption) {\n findOneArgs.populate = populateOption;\n }\n const currentDoc: any = await strapi.documents(item.uid as any).findOne(findOneArgs);\n if (!currentDoc) {\n throw new Error(`Document \"${item.documentId}\" not found in collection \"${item.uid}\".`);\n }\n wasPublished = Boolean(currentDoc?.publishedAt);\n\n const isRootDz = isDynamicZone;\n const existingRoot = currentDoc?.[rootKey] || (isRootDz ? [] : {});\n\n let restoredRoot: any;\n\n if (Array.isArray(item.dynamicZoneDiffs) && item.dynamicZoneDiffs.length > 0) {\n // If item recorded individual dynamic zone block diffs, revert each one\n let workingRoot = existingRoot;\n for (const dzDiff of item.dynamicZoneDiffs) {\n const parsedDz = parseDynamicZonePath(dzDiff.attribute || item.attribute);\n const dzParts = parsedDz.cleanPath.split('.').slice(1);\n const targetIndexes =\n dzDiff.index !== undefined\n ? [dzDiff.index]\n : parsedDz.targetIndex !== undefined\n ? [parsedDz.targetIndex]\n : undefined;\n workingRoot = setDeepProperty(workingRoot, dzParts, dzDiff.oldValue ?? null, {\n targetIndexes,\n targetComponentUid: dzDiff.componentUid || parsedDz.targetComponentUid,\n strapi,\n });\n }\n restoredRoot = workingRoot;\n } else {\n const parts = parsed.cleanPath.split('.');\n const pathParts = parts.slice(1);\n const targetIndexes = parsed.targetIndex !== undefined ? [parsed.targetIndex] : undefined;\n const targetComponentUid = parsed.targetComponentUid;\n\n restoredRoot = setDeepProperty(existingRoot, pathParts, rollbackPayload, {\n targetIndexes,\n targetComponentUid,\n strapi,\n });\n }\n\n await strapi.documents(item.uid as any).update({\n documentId: item.documentId,\n data: {\n [rootKey]: restoredRoot,\n },\n });\n } else {\n // Top-level scalar or relation\n const currentDoc: any = await strapi.documents(item.uid as any).findOne({\n documentId: item.documentId,\n });\n wasPublished = Boolean(currentDoc?.publishedAt);\n\n await strapi.documents(item.uid as any).update({\n documentId: item.documentId,\n data: {\n [item.attribute]: rollbackPayload,\n },\n });\n }\n\n if (ct?.options?.draftAndPublish && wasPublished) {\n try {\n await (strapi.documents(item.uid as any) as any).publish({\n documentId: item.documentId,\n });\n } catch (publishErr: any) {\n strapi.log.warn(`[bulk-updater] Failed to auto-publish rollback for ${item.uid}/${item.documentId}:`, publishErr?.message);\n }\n }\n\n // Record Content History Version for Strapi Content Manager\n try {\n await recordContentHistoryVersion(strapi, {\n uid: item.uid,\n documentId: item.documentId,\n userId,\n statusOverride: ct?.options?.draftAndPublish ? (wasPublished ? 'published' : 'draft') : undefined,\n });\n } catch {}\n\n try {\n const bulkService = strapi.plugin('bulk-updater').service('bulkUpdater');\n if (bulkService?.invalidateCache) {\n bulkService.invalidateCache(item.uid);\n }\n } catch {}\n\n revertedCount++;\n rollbackDetails.push({\n uid: item.uid,\n documentId: item.documentId,\n label: item.label,\n attribute: item.attribute,\n revertedTo: item.oldValue,\n status: 'reverted',\n });\n } catch (err: any) {\n rollbackDetails.push({\n uid: item.uid,\n documentId: item.documentId,\n label: item.label,\n status: 'error',\n message: err.message,\n });\n }\n }\n }\n\n return { revertedCount, rollbackDetails };\n },\n\n /**\n * Performs deterministic rollback of a batch\n */\n async rollbackBatch(batchId: string, currentUser?: any) {\n const config = this.getAuditConfig();\n if (!config.enabled) {\n throw new Error('Audit trail is not configured or disabled.');\n }\n\n if (config.mode === 'store') {\n const store = strapi.store({ type: 'plugin', name: 'bulk-updater', key: 'audit-history' });\n const stored = (await store.get({})) || { history: [] };\n const history = Array.isArray(stored.history) ? stored.history : [];\n\n const recordIndex = history.findIndex((r: any) => r.batchId === batchId);\n if (recordIndex === -1) {\n throw new Error(`Batch record with ID \"${batchId}\" was not found in audit trail.`);\n }\n\n const record = history[recordIndex];\n if (record.isRolledBack) {\n throw new Error(`Batch \"${batchId}\" has already been rolled back.`);\n }\n\n const diffs = Array.isArray(record.diffs) ? record.diffs : [];\n const { revertedCount, rollbackDetails } = await this.revertDiffItems(diffs, currentUser?.id);\n\n record.isRolledBack = true;\n record.rolledBackAt = new Date().toISOString();\n record.rolledBackBy = currentUser?.email || 'Admin';\n history[recordIndex] = record;\n await store.set({ value: { history } });\n\n try {\n const affectedUids = new Set(rollbackDetails.map((d: any) => d.uid));\n const bulkService = strapi.plugin('bulk-updater').service('bulkUpdater');\n affectedUids.forEach((uid: any) => {\n if (uid && bulkService?.invalidateCache) {\n bulkService.invalidateCache(uid);\n }\n });\n } catch {}\n\n await this.recordToEnterpriseNative(\n 'bulk-updater.rollback',\n {\n batchId,\n revertedCount,\n },\n currentUser\n );\n\n return {\n success: true,\n batchId,\n revertedCount,\n details: rollbackDetails,\n };\n }\n\n if (!config.contentType || !config.fields) {\n throw new Error('Audit trail is not configured or disabled.');\n }\n\n const f = config.fields;\n const records: any[] = await strapi.documents(config.contentType as any).findMany({\n filters: {\n [f.batchId]: { $eq: batchId },\n } as any,\n });\n\n const record = records?.[0];\n if (!record) {\n throw new Error(`Batch record with ID \"${batchId}\" was not found in audit trail.`);\n }\n\n if (record[f.isRolledBack]) {\n throw new Error(`Batch \"${batchId}\" has already been rolled back.`);\n }\n\n const diffs =\n typeof record[f.diffs] === 'string'\n ? JSON.parse(record[f.diffs])\n : record[f.diffs] || [];\n\n const { revertedCount, rollbackDetails } = await this.revertDiffItems(diffs, currentUser?.id);\n\n const updateData: any = {};\n if (f.isRolledBack) updateData[f.isRolledBack] = true;\n if (f.rolledBackAt) updateData[f.rolledBackAt] = new Date().toISOString();\n if (f.rolledBackBy) {\n updateData[f.rolledBackBy] = currentUser?.email || 'Admin';\n }\n\n await strapi.documents(config.contentType as any).update({\n documentId: record.documentId,\n data: updateData,\n });\n\n // Invalidate affected collection caches\n try {\n const affectedUids = new Set(rollbackDetails.map((d: any) => d.uid));\n const bulkService = strapi.plugin('bulk-updater').service('bulkUpdater');\n affectedUids.forEach((uid: any) => {\n if (uid && bulkService?.invalidateCache) {\n bulkService.invalidateCache(uid);\n }\n });\n } catch {}\n\n // Mirror rollback event to Strapi Enterprise native audit log if available\n await this.recordToEnterpriseNative(\n 'bulk-updater.rollback',\n {\n batchId,\n revertedCount,\n },\n currentUser\n );\n\n return {\n success: true,\n batchId,\n revertedCount,\n details: rollbackDetails,\n };\n },\n});\n","import type { Core } from '@strapi/strapi';\n\nexport interface ValidationRule {\n id: string;\n name: string;\n description?: string;\n collectionUid?: string; // specific collection UID (e.g. 'api::article.article') or '*' (all)\n targetField: string; // dot-path or attribute name, e.g. 'headingLevel' or 'st-featured.titleHeadingStyle.titleStyle'\n quotas: Record<string, number>;\n exceededAction: 'disable' | 'hide';\n enabled: boolean;\n scope: 'entry' | 'document';\n includeRichTextHtml?: boolean; // Scans rich text / CKEditor HTML / Markdown / Blocks headings\n richTextFields?: string[]; // Optional specific rich text paths to scan\n createdAt: string;\n updatedAt: string;\n}\n\nconst DEFAULT_RULES: ValidationRule[] = [\n {\n id: 'rule_seo_heading_h1',\n name: 'SEO Single H1 Page Rule',\n description: 'Enforces that only one H1 heading tag can be selected across all dynamic zone heading blocks within an entry, combined with rich text HTML.',\n collectionUid: '*',\n targetField: 'headingLevel',\n quotas: {\n h1: 1,\n h2: 3,\n },\n exceededAction: 'disable',\n enabled: true,\n scope: 'entry',\n includeRichTextHtml: true,\n richTextFields: [],\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n },\n];\n\n/**\n * Extracts heading counts (h1..h6) from rich text content (HTML strings, Markdown strings, or Strapi Blocks AST)\n */\nexport function extractHeadingsFromRichText(content: any): Record<string, number> {\n const counts: Record<string, number> = { h1: 0, h2: 0, h3: 0, h4: 0, h5: 0, h6: 0 };\n if (!content) return counts;\n\n // 1. Strapi 5 Blocks AST (Array of block nodes)\n if (Array.isArray(content)) {\n for (const node of content) {\n if (node && typeof node === 'object') {\n if (node.type === 'heading' && typeof node.level === 'number') {\n const tag = `h${node.level}`;\n if (counts[tag] !== undefined) counts[tag]++;\n }\n if (Array.isArray(node.children)) {\n const sub = extractHeadingsFromRichText(node.children);\n for (const k of Object.keys(counts)) counts[k] += sub[k];\n }\n }\n }\n return counts;\n }\n\n // 2. String (HTML or Markdown)\n if (typeof content === 'string') {\n for (let level = 1; level <= 6; level++) {\n const tag = `h${level}`;\n // HTML regex: <h1 ...> or <h1> (case-insensitive)\n const htmlMatches = content.match(new RegExp(`<${tag}\\\\b[^>]*>`, 'gi'));\n if (htmlMatches) {\n counts[tag] += htmlMatches.length;\n }\n // Markdown regex: '# Heading' at beginning of line\n const mdRegex = new RegExp(`(?:^|\\\\n)${'#'.repeat(level)}\\\\s+[^\\\\n]+`, 'g');\n const mdMatches = content.match(mdRegex);\n if (mdMatches) {\n counts[tag] += mdMatches.length;\n }\n }\n }\n\n return counts;\n}\n\nexport function cleanKey(str: string): string {\n return (str || '').replace(/[-_]/g, '').toLowerCase().trim();\n}\n\n/**\n * Matches a current property path against a rule targetField.\n * Supports:\n * - Leaf keys (e.g. 'titleStyle')\n * - Component dot paths (e.g. 'titleHeadingStyle.titleStyle')\n * - Dynamic zone paths (e.g. 'content.titleHeadingStyle.titleStyle')\n * - Collection-prefixed paths (e.g. 'st-featured.titleHeadingStyle.titleStyle' or 'api::st-featured.st-featured.titleHeadingStyle.titleStyle')\n * - Wildcards (e.g. 'content.*.titleHeadingStyle.titleStyle')\n * - Sequence matching through intermediate components or dynamic zones\n */\nexport function matchesPath(normalizedPath: string, leafKey: string, targetField: string): boolean {\n if (!targetField) return false;\n const pClean = cleanKey(normalizedPath);\n const kClean = cleanKey(leafKey);\n const tClean = cleanKey(targetField);\n\n // Exact or leaf match\n if (kClean === tClean || pClean === tClean) return true;\n\n // Split into dot-segments\n const targetSegments = targetField\n .replace(/^api::/i, '')\n .split('.')\n .map(cleanKey)\n .filter(Boolean);\n\n const pathSegments = normalizedPath\n .split('.')\n .map(cleanKey)\n .filter(Boolean);\n\n if (targetSegments.length === 0 || pathSegments.length === 0) return false;\n\n // 1. Single-segment targetField: matches leafKey or the final path segment\n if (targetSegments.length === 1) {\n const single = targetSegments[0];\n return kClean === single || pathSegments[pathSegments.length - 1] === single;\n }\n\n // 2. Direct suffix match (e.g. path 'content.titleHeadingStyle.titleStyle' ends with 'titleHeadingStyle.titleStyle')\n let isSuffix = true;\n for (let i = 0; i < targetSegments.length; i++) {\n const tSeg = targetSegments[targetSegments.length - 1 - i];\n const pSeg = pathSegments[pathSegments.length - 1 - i];\n if (tSeg !== '*' && tSeg !== pSeg) {\n isSuffix = false;\n break;\n }\n }\n if (isSuffix) return true;\n\n // 3. Collection prefix stripping: if targetField starts with collection name (e.g. 'st-featured.titleHeadingStyle.titleStyle')\n // Check if targetSegments without the first (or first two) elements matches suffix\n for (let startIdx = 1; startIdx < targetSegments.length; startIdx++) {\n const subTarget = targetSegments.slice(startIdx);\n if (subTarget.length > pathSegments.length) continue;\n let subSuffix = true;\n for (let i = 0; i < subTarget.length; i++) {\n const tSeg = subTarget[subTarget.length - 1 - i];\n const pSeg = pathSegments[pathSegments.length - 1 - i];\n if (tSeg !== '*' && tSeg !== pSeg) {\n subSuffix = false;\n break;\n }\n }\n if (subSuffix) return true;\n }\n\n // 4. In-order sequence match: all target segments appear in relative order along pathSegments\n // e.g. target ['content', 'titleheadingstyle', 'titlestyle'] matches ['content', 'zones', 'herobanner', 'titleheadingstyle', 'titlestyle']\n let pIdx = 0;\n let matchesInOrder = true;\n let tStart = 0;\n // If first target segment looks like collection name and doesn't match first path segment, skip it\n if (targetSegments.length > 2 && targetSegments[0] !== pathSegments[0] && targetSegments[0] !== '*') {\n tStart = 1;\n }\n for (let tIdx = tStart; tIdx < targetSegments.length; tIdx++) {\n const tSeg = targetSegments[tIdx];\n if (tSeg === '*') continue;\n let found = false;\n while (pIdx < pathSegments.length) {\n if (pathSegments[pIdx] === tSeg) {\n found = true;\n pIdx++;\n break;\n }\n pIdx++;\n }\n if (!found) {\n matchesInOrder = false;\n break;\n }\n }\n\n return matchesInOrder;\n}\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => ({\n async getStore() {\n return strapi.store({\n type: 'plugin',\n name: 'bulk-updater',\n key: 'validation-rules',\n });\n },\n\n async getRules(): Promise<ValidationRule[]> {\n const store = await this.getStore();\n const stored = await store.get({});\n if (!stored || !Array.isArray(stored.rules)) {\n // Seed default rules if first time\n await store.set({ value: { rules: DEFAULT_RULES } });\n return DEFAULT_RULES;\n }\n return stored.rules;\n },\n\n async saveRule(ruleData: Partial<ValidationRule>): Promise<ValidationRule> {\n const store = await this.getStore();\n const rules = await this.getRules();\n\n const now = new Date().toISOString();\n let savedRule: ValidationRule;\n\n if (ruleData.id) {\n // Update existing\n const index = rules.findIndex((r) => r.id === ruleData.id);\n if (index !== -1) {\n savedRule = {\n ...rules[index],\n ...ruleData,\n collectionUid: ruleData.collectionUid !== undefined ? ruleData.collectionUid : (rules[index].collectionUid || '*'),\n includeRichTextHtml: ruleData.includeRichTextHtml !== undefined ? Boolean(ruleData.includeRichTextHtml) : Boolean(rules[index].includeRichTextHtml),\n richTextFields: Array.isArray(ruleData.richTextFields) ? ruleData.richTextFields : (rules[index].richTextFields || []),\n updatedAt: now,\n } as ValidationRule;\n rules[index] = savedRule;\n } else {\n savedRule = {\n id: ruleData.id,\n name: ruleData.name || 'New Rule',\n description: ruleData.description || '',\n collectionUid: ruleData.collectionUid || '*',\n targetField: ruleData.targetField || 'headingLevel',\n quotas: ruleData.quotas || { h1: 1 },\n exceededAction: ruleData.exceededAction || 'disable',\n enabled: ruleData.enabled ?? true,\n scope: ruleData.scope || 'entry',\n includeRichTextHtml: Boolean(ruleData.includeRichTextHtml),\n richTextFields: Array.isArray(ruleData.richTextFields) ? ruleData.richTextFields : [],\n createdAt: now,\n updatedAt: now,\n };\n rules.push(savedRule);\n }\n } else {\n // Create new\n const id = `rule_${Date.now()}_${Math.random().toString(36).substring(2, 6)}`;\n savedRule = {\n id,\n name: ruleData.name || 'Custom Quota Rule',\n description: ruleData.description || '',\n collectionUid: ruleData.collectionUid || '*',\n targetField: ruleData.targetField || 'headingLevel',\n quotas: ruleData.quotas || { h1: 1 },\n exceededAction: ruleData.exceededAction || 'disable',\n enabled: ruleData.enabled ?? true,\n scope: ruleData.scope || 'entry',\n includeRichTextHtml: Boolean(ruleData.includeRichTextHtml),\n richTextFields: Array.isArray(ruleData.richTextFields) ? ruleData.richTextFields : [],\n createdAt: now,\n updatedAt: now,\n };\n rules.push(savedRule);\n }\n\n await store.set({ value: { rules } });\n return savedRule;\n },\n\n async deleteRule(ruleId: string): Promise<boolean> {\n const store = await this.getStore();\n const rules = await this.getRules();\n const filtered = rules.filter((r) => r.id !== ruleId);\n await store.set({ value: { rules: filtered } });\n return true;\n },\n\n async toggleRule(ruleId: string, enabled?: boolean): Promise<ValidationRule | null> {\n const store = await this.getStore();\n const rules = await this.getRules();\n const index = rules.findIndex((r) => r.id === ruleId);\n if (index === -1) return null;\n\n const current = rules[index];\n const newEnabled = typeof enabled === 'boolean' ? enabled : !current.enabled;\n const updated = {\n ...current,\n enabled: newEnabled,\n updatedAt: new Date().toISOString(),\n };\n rules[index] = updated;\n await store.set({ value: { rules } });\n return updated;\n },\n\n async scanViolations(ruleId: string): Promise<{\n rule: ValidationRule;\n totalScanned: number;\n totalViolations: number;\n violations: Array<{\n uid: string;\n collectionDisplayName: string;\n documentId: string;\n entryLabel: string;\n violatingOption: string;\n foundCount: number;\n structuredCount: number;\n richTextCount: number;\n maxAllowed: number;\n editUrl: string;\n detail?: string;\n }>;\n }> {\n const rules = await this.getRules();\n const rule = rules.find((r) => r.id === ruleId);\n if (!rule) {\n throw new Error(`Validation rule ${ruleId} not found`);\n }\n\n const targetField = rule.targetField;\n const quotas = rule.quotas || {};\n const violations: Array<any> = [];\n let totalScanned = 0;\n\n const allContentTypes = strapi.contentTypes || {};\n const allComponents = strapi.components || {};\n\n function componentHasField(compUid: string, targetField: string): boolean {\n const comp = allComponents[compUid];\n if (!comp?.attributes) return false;\n if (matchesPath(compUid, compUid, targetField)) return true;\n for (const [attrName, attrDef] of Object.entries(comp.attributes) as any[]) {\n if (matchesPath(attrName, attrName, targetField) || matchesPath(`${compUid}.${attrName}`, attrName, targetField)) return true;\n if (attrDef.type === 'component' && attrDef.component) {\n if (componentHasField(attrDef.component, targetField)) return true;\n } else if (attrDef.type === 'dynamiczone' && Array.isArray(attrDef.components)) {\n if (attrDef.components.some((c: string) => componentHasField(c, targetField))) return true;\n }\n }\n return false;\n }\n\n // Helper: Checks if a content-type schema or any of its components has the target field\n function schemaHasField(ctSchema: any): { hasField: boolean; populateAttrs: Record<string, any> } {\n if (!ctSchema || !ctSchema.attributes) return { hasField: false, populateAttrs: {} };\n const rawAttrs = ctSchema.attributes;\n const populateAttrs: Record<string, any> = {};\n let hasField = false;\n\n for (const [attrKey, attrDef] of Object.entries(rawAttrs) as any[]) {\n if (matchesPath(attrKey, attrKey, targetField)) {\n hasField = true;\n }\n if (attrDef.type === 'component' && attrDef.component) {\n if (componentHasField(attrDef.component, targetField)) {\n hasField = true;\n populateAttrs[attrKey] = { populate: '*' };\n }\n } else if (attrDef.type === 'dynamiczone' && Array.isArray(attrDef.components)) {\n const matchingComp = attrDef.components.some(\n (compUid: string) => componentHasField(compUid, targetField) || matchesPath(`${attrKey}.${compUid}`, compUid, targetField)\n );\n if (matchingComp) {\n hasField = true;\n populateAttrs[attrKey] = { populate: '*' };\n }\n }\n }\n\n return { hasField, populateAttrs };\n }\n\n const candidateUids = Object.keys(allContentTypes).filter((uid) => {\n if (!uid.startsWith('api::') || uid.includes('bulk-updater')) return false;\n if (rule.collectionUid && rule.collectionUid !== '*') {\n if (rule.collectionUid === uid) return true;\n const cleanRuleCol = cleanKey(rule.collectionUid);\n const cleanUid = cleanKey(uid);\n if (cleanUid.includes(cleanRuleCol) || cleanRuleCol.includes(cleanUid)) return true;\n return false;\n }\n return true;\n });\n\n // Filter candidate collections to those that possess targetField in schema, OR if rule has collectionUid specified\n const relevantCollections: Array<{ uid: string; displayName: string; populateOption?: Record<string, any> | string }> = [];\n for (const uid of candidateUids) {\n const ct = allContentTypes[uid];\n if (!ct) continue;\n const { hasField, populateAttrs } = schemaHasField(ct);\n const isTargetCol = rule.collectionUid && (rule.collectionUid === uid || cleanKey(uid).includes(cleanKey(rule.collectionUid)));\n if (hasField || isTargetCol) {\n relevantCollections.push({\n uid,\n displayName: ct.info?.displayName || uid,\n populateOption: Object.keys(populateAttrs).length > 0 ? populateAttrs : '*',\n });\n }\n }\n\n const BATCH_SIZE = 250;\n\n await Promise.all(\n relevantCollections.map(async ({ uid, displayName, populateOption }) => {\n try {\n let page = 1;\n while (true) {\n const entries: any[] = await strapi.documents(uid as any).findMany({\n page,\n pageSize: BATCH_SIZE,\n populate: populateOption,\n });\n\n if (!entries || entries.length === 0) break;\n\n for (const entry of entries) {\n totalScanned++;\n const structuredCounts: Record<string, number> = {};\n const richTextCounts: Record<string, number> = { h1: 0, h2: 0, h3: 0, h4: 0, h5: 0, h6: 0 };\n\n function traverse(obj: any, currentPath = '') {\n if (!obj || typeof obj !== 'object') return;\n const compName = typeof obj.__component === 'string' ? obj.__component : '';\n\n for (const key of Object.keys(obj)) {\n if (key === '__component') continue;\n const val = obj[key];\n const newPath = currentPath ? `${currentPath}.${key}` : key;\n const normalizedPath = newPath.replace(/\\.\\d+/g, '');\n\n const compPath = compName\n ? (currentPath ? `${currentPath}.${compName}.${key}` : `${compName}.${key}`).replace(/\\.\\d+/g, '')\n : '';\n\n const isMatch = matchesPath(normalizedPath, key, targetField) ||\n (compPath ? matchesPath(compPath, key, targetField) : false);\n\n if (isMatch && typeof val === 'string' && val.trim()) {\n const lower = val.toLowerCase().trim();\n structuredCounts[lower] = (structuredCounts[lower] || 0) + 1;\n }\n\n if (rule.includeRichTextHtml) {\n if (typeof val === 'string' && (val.includes('<h') || val.includes('#'))) {\n const headings = extractHeadingsFromRichText(val);\n for (const [tag, count] of Object.entries(headings)) {\n if (count > 0) {\n richTextCounts[tag] = (richTextCounts[tag] || 0) + count;\n }\n }\n } else if (Array.isArray(val) && val.length > 0 && typeof val[0] === 'object' && val[0]?.type) {\n const headings = extractHeadingsFromRichText(val);\n for (const [tag, count] of Object.entries(headings)) {\n if (count > 0) {\n richTextCounts[tag] = (richTextCounts[tag] || 0) + count;\n }\n }\n continue;\n }\n }\n\n if (typeof val === 'object' && val !== null) {\n traverse(val, newPath);\n }\n }\n }\n\n traverse(entry);\n\n for (const [optKey, max] of Object.entries(quotas)) {\n const lowerOpt = optKey.toLowerCase().trim();\n const structCount = structuredCounts[lowerOpt] || 0;\n const rtCount = rule.includeRichTextHtml ? (richTextCounts[lowerOpt] || 0) : 0;\n const combinedCount = structCount + rtCount;\n\n if (combinedCount > max) {\n const entryLabel =\n entry.title || entry.name || entry.email || `Entry #${entry.documentId}`;\n \n let detail = '';\n if (rtCount > 0 && structCount > 0) {\n detail = `${structCount} structured + ${rtCount} in rich text HTML`;\n } else if (rtCount > 0) {\n detail = `${rtCount} in rich text HTML / Markdown`;\n } else {\n detail = `${structCount} in structured component`;\n }\n\n violations.push({\n uid,\n collectionDisplayName: displayName,\n documentId: entry.documentId,\n entryLabel,\n violatingOption: optKey.toUpperCase(),\n foundCount: combinedCount,\n structuredCount: structCount,\n richTextCount: rtCount,\n maxAllowed: max,\n detail,\n editUrl: `/admin/content-manager/collection-types/${uid}/${entry.documentId}`,\n });\n }\n }\n }\n\n if (entries.length < BATCH_SIZE) break;\n page++;\n }\n } catch (err) {\n strapi.log.warn(`[bulk-updater] Failed scanning ${uid} for rule ${ruleId}:`, err);\n }\n })\n );\n\n return {\n rule,\n totalScanned,\n totalViolations: violations.length,\n violations,\n };\n },\n});\n","import type { Core } from '@strapi/strapi';\nimport { recordContentHistoryVersion } from './content-history';\nimport {\n getExecutionWindowConfig,\n checkBusinessHours,\n registerPendingBatch,\n type PendingBatch,\n} from './bulk-updater';\nimport { extractHeadingsFromRichText } from './validation-rules';\n\n/**\n * Robust, Excel-Safe CSV string escaping helper (RFC-4180 compliant)\n */\nfunction escapeCsvValue(val: any): string {\n if (val === null || val === undefined) return '';\n let str = '';\n\n if (val instanceof Date) {\n str = val.toISOString();\n } else if (typeof val === 'object') {\n str = JSON.stringify(val);\n } else {\n str = String(val);\n }\n\n // Normalize CRLF or lone CR inside cells to standard LF\n str = str.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\n\n // Excel CSV Formula Injection Mitigation:\n // If first character is =, +, -, or @, prefix with a single quote to prevent execution in Excel\n if (/^[=+@-]$/.test(str.charAt(0))) {\n str = `'${str}`;\n }\n\n // Quote cell if it contains delimiter, quotes, or newlines\n if (str.includes(',') || str.includes('\"') || str.includes('\\n')) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n return str;\n}\n\n/**\n * RFC-4180 compliant CSV parser that correctly handles:\n * - Multiline strings & HTML content with embedded line breaks (\\n, \\r\\n, \\r) inside quotes\n * - Commas embedded inside double-quoted cells without shifting subsequent columns\n * - Escaped double quotes (\"\" -> \")\n * - Leading/trailing whitespace outside quotes\n * - UTF-8 Byte Order Mark (BOM)\n * - Excel formula injection unescaping ('=, '+, '-, '@)\n */\nexport function parseCsvRows(csvText: string): string[][] {\n if (!csvText) return [];\n\n // Strip UTF-8 BOM if present\n let text = csvText;\n if (text.charCodeAt(0) === 0xfeff) {\n text = text.slice(1);\n }\n\n const rows: string[][] = [];\n let currentRow: string[] = [];\n let currentCell = '';\n let inQuotes = false;\n let cellIsQuoted = false;\n\n for (let i = 0; i < text.length; i++) {\n const char = text[i];\n const nextChar = text[i + 1];\n\n if (inQuotes) {\n if (char === '\"') {\n if (nextChar === '\"') {\n // Escaped quote: \"\" -> \"\n currentCell += '\"';\n i++; // skip second quote\n } else {\n // Closing quote\n inQuotes = false;\n }\n } else {\n // Any character inside quotes (including \\r, \\n, commas, HTML tags) is preserved verbatim\n currentCell += char;\n }\n } else {\n if (char === '\"' && !cellIsQuoted && currentCell.trim() === '') {\n // Opening quote (discards leading whitespace before opening quote)\n inQuotes = true;\n cellIsQuoted = true;\n currentCell = '';\n } else if (char === ',') {\n currentRow.push(cellIsQuoted ? currentCell : currentCell.trim());\n currentCell = '';\n cellIsQuoted = false;\n } else if (char === '\\r') {\n if (nextChar === '\\n') {\n i++; // Skip \\n in \\r\\n sequence\n }\n currentRow.push(cellIsQuoted ? currentCell : currentCell.trim());\n if (currentRow.length > 1 || (currentRow.length === 1 && currentRow[0] !== '')) {\n rows.push(currentRow);\n }\n currentRow = [];\n currentCell = '';\n cellIsQuoted = false;\n } else if (char === '\\n') {\n currentRow.push(cellIsQuoted ? currentCell : currentCell.trim());\n if (currentRow.length > 1 || (currentRow.length === 1 && currentRow[0] !== '')) {\n rows.push(currentRow);\n }\n currentRow = [];\n currentCell = '';\n cellIsQuoted = false;\n } else {\n // If cell was already quoted and closed, ignore trailing whitespace between closing quote and delimiter\n if (!(cellIsQuoted && !inQuotes && (char === ' ' || char === '\\t'))) {\n currentCell += char;\n }\n }\n }\n }\n\n if (currentCell !== '' || cellIsQuoted || currentRow.length > 0) {\n currentRow.push(cellIsQuoted ? currentCell : currentCell.trim());\n if (currentRow.length > 1 || (currentRow.length === 1 && currentRow[0] !== '')) {\n rows.push(currentRow);\n }\n }\n\n return rows;\n}\n\nexport function parseCsv(csvText: string): Array<Record<string, string>> {\n const rows = parseCsvRows(csvText);\n if (rows.length < 2) return [];\n\n const headers = rows[0].map((h) => h.trim());\n const records: Array<Record<string, string>> = [];\n\n for (let i = 1; i < rows.length; i++) {\n const row = rows[i];\n const record: Record<string, string> = {};\n headers.forEach((h, idx) => {\n let val = row[idx] !== undefined ? row[idx] : '';\n if (typeof val === 'string' && /^'[=+@-]/.test(val)) {\n val = val.substring(1);\n }\n record[h] = val;\n });\n records.push(record);\n }\n\n return records;\n}\n\nconst LIFECYCLE_STATUS_WORDS = new Set([\n 'pending review',\n 'pending_review',\n 'pending approval',\n 'pending_approval',\n 'approved',\n 'rejected',\n 'draft',\n 'published',\n 'modified',\n 'supported',\n 'ignored',\n]);\n\nexport function isValidDocId(val: any): boolean {\n if (!val || typeof val !== 'string') return false;\n const trimmed = val.trim();\n if (!trimmed) return false;\n if (LIFECYCLE_STATUS_WORDS.has(trimmed.toLowerCase())) return false;\n if (/\\s/.test(trimmed)) return false;\n return /^[a-zA-Z0-9_-]+$/.test(trimmed);\n}\n\nexport function extractDocId(row: Record<string, any>): string {\n if (!row || typeof row !== 'object') return '';\n const candidates = [\n row.documentId,\n row.document_id,\n row['Document ID'],\n row['Document Id'],\n row['document_id'],\n row.docId,\n row['docId'],\n row.id,\n row.ID,\n row.Id,\n ];\n for (const c of candidates) {\n if (c !== undefined && c !== null) {\n const str = String(c).trim();\n if (isValidDocId(str)) {\n return str;\n }\n }\n }\n return '';\n}\n\nexport function extractLocale(row: Record<string, any>): string | undefined {\n if (!row || typeof row !== 'object') return undefined;\n const candidates = [row.locale, row.Locale, row['locale'], row['Locale']];\n for (const c of candidates) {\n if (c !== undefined && c !== null) {\n const str = String(c).trim();\n if (str && str.toLowerCase() !== 'null' && str.toLowerCase() !== 'undefined') {\n return str;\n }\n }\n }\n return undefined;\n}\n\nexport function extractDetailedErrorMessage(err: any): string {\n if (!err) return 'Error processing row';\n\n // 1. Check err.details?.errors or err.error?.details?.errors (Strapi / Yup standard format)\n const detailsErrors = err.details?.errors || err.error?.details?.errors;\n if (Array.isArray(detailsErrors) && detailsErrors.length > 0) {\n const messages = detailsErrors\n .map((e: any) => {\n if (!e) return '';\n const path = Array.isArray(e.path) ? e.path.join('.') : e.path;\n const msg = e.message || (typeof e === 'string' ? e : JSON.stringify(e));\n return path ? `${path}: ${msg}` : msg;\n })\n .filter(Boolean);\n if (messages.length > 0) return messages.join('; ');\n }\n\n // 2. Check err.inner (Yup's nested ValidationError instances)\n if (Array.isArray(err.inner) && err.inner.length > 0) {\n const messages = err.inner\n .map((e: any) => {\n if (!e) return '';\n const path = e.path;\n const msg = e.message || (typeof e === 'string' ? e : JSON.stringify(e));\n return path ? `${path}: ${msg}` : msg;\n })\n .filter(Boolean);\n if (messages.length > 0) return messages.join('; ');\n }\n\n // 3. Check err.errors (Yup validation error string array)\n if (Array.isArray(err.errors) && err.errors.length > 0) {\n return err.errors.join('; ');\n }\n\n // 4. Check err.details if it is a string or object with message\n if (typeof err.details === 'string' && err.details.trim()) {\n return err.details;\n }\n if (err.details?.message) {\n return err.details.message;\n }\n\n // 5. Check err.message if descriptive\n if (err.message && err.message !== '[object Object]') {\n return err.message;\n }\n\n return 'Error processing row';\n}\n\n/**\n * Field definition discovered for export\n */\ninterface ExportFieldDef {\n key: string;\n label: string;\n type: string;\n}\n\n/**\n * Recursively discovers all exportable fields, fully supporting nested components\n */\nfunction discoverExportFields(\n ct: any,\n allComponents: Record<string, any>,\n maxDepth = 4\n): ExportFieldDef[] {\n const fields: ExportFieldDef[] = [{ key: 'documentId', label: 'documentId', type: 'string' }];\n const excluded = ['createdBy', 'updatedBy', 'localizations'];\n\n function walkComponent(compUid: string, pathPrefix: string, labelPrefix: string, depth: number) {\n if (depth >= maxDepth) return;\n const comp = allComponents[compUid];\n if (!comp?.attributes) return;\n\n for (const [subKey, subDef] of Object.entries(comp.attributes) as any[]) {\n if (excluded.includes(subKey)) continue;\n const keyPath = `${pathPrefix}.${subKey}`;\n const displayLabel = `${labelPrefix} > ${subKey}`;\n\n if (subDef.type === 'component' && subDef.component) {\n if (!subDef.repeatable) {\n walkComponent(subDef.component, keyPath, displayLabel, depth + 1);\n } else {\n fields.push({ key: keyPath, label: displayLabel, type: 'component' });\n }\n } else {\n fields.push({ key: keyPath, label: displayLabel, type: subDef.type });\n }\n }\n }\n\n for (const [attrName, attrDef] of Object.entries(ct.attributes || {}) as any[]) {\n if (excluded.includes(attrName)) continue;\n if (attrDef.type === 'component' && attrDef.component) {\n if (!attrDef.repeatable) {\n walkComponent(attrDef.component, attrName, attrName, 0);\n } else {\n fields.push({ key: attrName, label: attrName, type: 'component' });\n }\n } else {\n fields.push({ key: attrName, label: attrName, type: attrDef.type });\n }\n }\n\n return fields;\n}\n\n/**\n * Builds a deep populate object for Strapi 5 Document Service\n */\nfunction buildDeepPopulate(\n attributes: Record<string, any>,\n allComponents: Record<string, any>,\n depth = 0\n): Record<string, any> | undefined {\n if (depth > 5) return undefined;\n const populate: Record<string, any> = {};\n\n for (const [key, def] of Object.entries(attributes || {}) as any[]) {\n if (def.type === 'component' && def.component) {\n const comp = allComponents[def.component];\n if (comp?.attributes) {\n const subPopulate = buildDeepPopulate(comp.attributes, allComponents, depth + 1);\n if (subPopulate && Object.keys(subPopulate).length > 0) {\n populate[key] = {\n populate: subPopulate,\n };\n } else {\n populate[key] = true;\n }\n } else {\n populate[key] = true;\n }\n } else if (def.type === 'dynamiczone') {\n populate[key] = true;\n } else if (def.type === 'relation' || def.type === 'media') {\n populate[key] = true;\n }\n }\n\n return Object.keys(populate).length > 0 ? populate : undefined;\n}\n\n/**\n * Safely resolves deep nested dot-notation paths (e.g. \"defaultSeo.metaDescription\" or \"author.name\")\n */\nfunction getNestedExportValue(entry: any, path: string): any {\n if (!entry || !path) return '';\n const parts = path.split('.');\n let current: any = entry;\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n if (current === null || current === undefined) return '';\n\n if (Array.isArray(current)) {\n // Repeatable component or array: extract remainder for each element\n const subPath = parts.slice(i).join('.');\n return current\n .map((item) => {\n if (!item) return '';\n if (typeof item === 'object') {\n const val = getNestedExportValue(item, subPath);\n return typeof val === 'object' ? JSON.stringify(val) : String(val ?? '');\n }\n return String(item);\n })\n .filter(Boolean)\n .join('; ');\n }\n\n if (current && typeof current === 'object') {\n if (current[part] !== undefined) {\n current = current[part];\n } else {\n const camel = part.replace(/_([a-z0-9])/g, (_, l) => l.toUpperCase());\n const snake = part.replace(/([A-Z])/g, '_$1').toLowerCase();\n if (current[camel] !== undefined) {\n current = current[camel];\n } else if (current[snake] !== undefined) {\n current = current[snake];\n } else {\n current = undefined;\n }\n }\n } else {\n current = undefined;\n }\n }\n\n if (current === null || current === undefined) return '';\n\n // If Media object\n if (typeof current === 'object' && current.url) {\n return current.url;\n }\n\n // If Relation object\n if (typeof current === 'object' && !Array.isArray(current)) {\n if (current.documentId || current.name || current.title) {\n return current.name || current.title || current.documentId;\n }\n }\n\n // If array of objects (e.g. relations or components)\n if (Array.isArray(current)) {\n return current\n .map((item) => {\n if (!item) return '';\n if (typeof item === 'object') {\n return item.name || item.title || item.documentId || JSON.stringify(item);\n }\n return String(item);\n })\n .filter(Boolean)\n .join('; ');\n }\n\n return current;\n}\n\n\nexport interface ProcessRowsStats {\n total: number;\n created: number;\n updated: number;\n skipped: number;\n newWithoutDocId: number;\n errors: Array<{ row: number; error: string; documentId?: string }>;\n diffs: Array<any>;\n}\n\ninterface CsvImportSession {\n batchId: string;\n uid: string;\n createdAt: number;\n total: number;\n created: number;\n updated: number;\n skipped: number;\n newWithoutDocId: number;\n errors: Array<{ row: number; error: string; documentId?: string }>;\n diffs: Array<any>;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n}\n\nconst csvImportSessions = new Map<string, CsvImportSession>();\n\nfunction cleanupStaleSessions() {\n const oneHourAgo = Date.now() - 3600000;\n for (const [id, session] of csvImportSessions.entries()) {\n if (session.createdAt < oneHourAgo) {\n csvImportSessions.delete(id);\n }\n }\n}\n\nconst SYSTEM_FIELD_KEYS = new Set([\n 'documentid',\n 'document_id',\n 'docid',\n 'id',\n 'createdat',\n 'updatedat',\n 'publishedat',\n 'createdby',\n 'updatedby',\n 'localizations',\n 'locale',\n 'status',\n]);\n\nasync function findExistingDocument(\n strapi: Core.Strapi,\n uid: string,\n targetDocId: string,\n docLocale?: string\n): Promise<any> {\n if (!targetDocId) return null;\n try {\n const queryArgs: any = { documentId: targetDocId };\n if (docLocale) queryArgs.locale = docLocale;\n const found = await (strapi.documents(uid as any) as any).findOne(queryArgs);\n if (found) return found;\n } catch {\n // Strapi 5 throws NotFoundError if documentId does not exist\n }\n\n if (/^\\d+$/.test(targetDocId)) {\n try {\n const queryArgs: any = {\n filters: { id: parseInt(targetDocId, 10) },\n limit: 1,\n };\n if (docLocale) queryArgs.locale = docLocale;\n const list = await (strapi.documents(uid as any) as any).findMany(queryArgs);\n if (list && list.length > 0) return list[0];\n } catch {\n // Ignore\n }\n }\n\n return null;\n}\n\n/**\n * Recursively deep merges two component objects while preserving array values and existing properties.\n */\nfunction deepMergeComponent(existingVal: any, newVal: any): any {\n if (!existingVal || typeof existingVal !== 'object' || Array.isArray(existingVal)) {\n return newVal;\n }\n if (!newVal || typeof newVal !== 'object' || Array.isArray(newVal)) {\n return newVal;\n }\n const merged = { ...existingVal };\n for (const k of Object.keys(newVal)) {\n if (newVal[k] && typeof newVal[k] === 'object' && !Array.isArray(newVal[k])) {\n merged[k] = deepMergeComponent(existingVal[k], newVal[k]);\n } else if (newVal[k] !== undefined) {\n merged[k] = newVal[k];\n }\n }\n return merged;\n}\n\n/**\n * Transforms and casts row CSV columns into Strapi schema field types,\n * supporting nested components (dot-notation), relations, dynamic zones, and primitive types.\n */\nexport function parseRowToPayload(\n strapi: Core.Strapi,\n attrs: any,\n row: Record<string, string>\n): Record<string, any> {\n const payload: Record<string, any> = {};\n\n for (const [key, rawVal] of Object.entries(row)) {\n const normalizedKey = key.toLowerCase().replace(/[\\s_-]/g, '');\n if (SYSTEM_FIELD_KEYS.has(normalizedKey)) continue;\n\n if (key.includes('.')) {\n const parts = key.split('.');\n let currentAttrs = attrs;\n let currentTarget = payload;\n let validPath = true;\n\n for (let pIdx = 0; pIdx < parts.length; pIdx++) {\n const part = parts[pIdx];\n const isLeaf = pIdx === parts.length - 1;\n\n if (isLeaf) {\n let leafDef = currentAttrs[part];\n if (!leafDef) {\n const match = Object.keys(currentAttrs).find(\n (k) => k.toLowerCase() === part.toLowerCase() || k.toLowerCase() === part.toLowerCase().replace(/\\s+/g, '')\n );\n if (match) leafDef = currentAttrs[match];\n }\n if (!leafDef) {\n validPath = false;\n break;\n }\n\n // Cast and assign leaf value\n if (rawVal === '' || rawVal === null || rawVal === undefined) {\n if (leafDef.type !== 'dynamiczone' && !(leafDef.type === 'component' && leafDef.repeatable) && leafDef.type !== 'relation') {\n currentTarget[part] = null;\n }\n } else if (leafDef.type === 'integer' || leafDef.type === 'biginteger') {\n const parsedInt = parseInt(rawVal, 10);\n currentTarget[part] = isNaN(parsedInt) ? null : parsedInt;\n } else if (leafDef.type === 'float' || leafDef.type === 'decimal') {\n const parsedFloat = parseFloat(rawVal);\n currentTarget[part] = isNaN(parsedFloat) ? null : parsedFloat;\n } else if (leafDef.type === 'boolean') {\n currentTarget[part] = rawVal.toLowerCase() === 'true' || rawVal === '1';\n } else if (leafDef.type === 'json') {\n try {\n currentTarget[part] = JSON.parse(rawVal);\n } catch {\n currentTarget[part] = rawVal;\n }\n } else if (leafDef.type === 'component' && leafDef.repeatable) {\n try {\n const parsed = JSON.parse(rawVal);\n if (Array.isArray(parsed)) {\n currentTarget[part] = parsed;\n }\n } catch {}\n } else if (leafDef.type === 'relation') {\n try {\n const parsed = JSON.parse(rawVal);\n if (Array.isArray(parsed) || (typeof parsed === 'object' && parsed !== null)) {\n currentTarget[part] = parsed;\n } else if (isValidDocId(rawVal)) {\n currentTarget[part] = rawVal;\n }\n } catch {\n if (isValidDocId(rawVal)) {\n currentTarget[part] = rawVal;\n }\n }\n } else {\n currentTarget[part] = rawVal;\n }\n } else {\n // Intermediate segment\n let compDef = currentAttrs[part];\n if (!compDef) {\n const match = Object.keys(currentAttrs).find(\n (k) => k.toLowerCase() === part.toLowerCase() || k.toLowerCase() === part.toLowerCase().replace(/\\s+/g, '')\n );\n if (match) compDef = currentAttrs[match];\n }\n\n if (compDef?.type === 'component' && !compDef.repeatable && compDef.component) {\n const comp = strapi.components[compDef.component];\n if (!comp?.attributes) {\n validPath = false;\n break;\n }\n if (!currentTarget[part] || typeof currentTarget[part] !== 'object' || Array.isArray(currentTarget[part])) {\n currentTarget[part] = {};\n }\n currentTarget = currentTarget[part];\n currentAttrs = comp.attributes;\n } else {\n validPath = false;\n break;\n }\n }\n }\n continue;\n }\n\n let attrDef = attrs[key];\n if (!attrDef) {\n const matchKey = Object.keys(attrs).find(\n (k) => k.toLowerCase() === key.toLowerCase() || k.toLowerCase() === key.toLowerCase().replace(/\\s+/g, '')\n );\n if (matchKey) {\n attrDef = attrs[matchKey];\n }\n }\n if (!attrDef) continue; // Skip unknown columns\n\n if (rawVal === '' || rawVal === null || rawVal === undefined) {\n if (attrDef.type !== 'dynamiczone' && !(attrDef.type === 'component' && attrDef.repeatable)) {\n payload[key] = null;\n }\n continue;\n }\n\n switch (attrDef.type) {\n case 'integer':\n case 'biginteger': {\n const parsedInt = parseInt(rawVal, 10);\n payload[key] = isNaN(parsedInt) ? null : parsedInt;\n break;\n }\n case 'float':\n case 'decimal': {\n const parsedFloat = parseFloat(rawVal);\n payload[key] = isNaN(parsedFloat) ? null : parsedFloat;\n break;\n }\n case 'boolean':\n payload[key] = rawVal.toLowerCase() === 'true' || rawVal === '1';\n break;\n case 'json':\n try {\n payload[key] = JSON.parse(rawVal);\n } catch {\n payload[key] = rawVal;\n }\n break;\n case 'dynamiczone': {\n try {\n const parsed = JSON.parse(rawVal);\n if (\n Array.isArray(parsed) &&\n parsed.every((item) => item && typeof item === 'object' && typeof item.__component === 'string')\n ) {\n payload[key] = parsed;\n }\n } catch {}\n break;\n }\n case 'component': {\n if (attrDef.repeatable) {\n try {\n const parsed = JSON.parse(rawVal);\n if (Array.isArray(parsed) && parsed.every((item) => item && typeof item === 'object')) {\n payload[key] = parsed;\n }\n } catch {}\n } else {\n try {\n const parsed = JSON.parse(rawVal);\n if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {\n payload[key] = parsed;\n }\n } catch {}\n }\n break;\n }\n case 'relation': {\n try {\n const parsed = JSON.parse(rawVal);\n if (Array.isArray(parsed) || (typeof parsed === 'object' && parsed !== null)) {\n payload[key] = parsed;\n break;\n }\n } catch {}\n\n if (isValidDocId(rawVal)) {\n payload[key] = rawVal;\n } else if (rawVal.includes(';') || rawVal.includes(',')) {\n const parts = rawVal.split(/[;,]/).map((s) => s.trim()).filter(Boolean);\n if (parts.length > 0 && parts.every((p) => isValidDocId(p))) {\n payload[key] = parts;\n }\n }\n break;\n }\n case 'media': {\n if (/^\\d+$/.test(rawVal.trim())) {\n payload[key] = parseInt(rawVal.trim(), 10);\n } else {\n try {\n const parsed = JSON.parse(rawVal);\n if (typeof parsed === 'number' || typeof parsed === 'object') {\n payload[key] = parsed;\n }\n } catch {}\n }\n break;\n }\n default:\n payload[key] = rawVal;\n }\n }\n\n return payload;\n}\n\nfunction formatValueDisplay(val: any): string {\n if (val === null || val === undefined) return '(empty)';\n if (typeof val === 'object') {\n try {\n return JSON.stringify(val);\n } catch {\n return String(val);\n }\n }\n const s = String(val).trim();\n return s === '' ? '(empty)' : s;\n}\n\nexport async function processCsvRows(\n strapi: Core.Strapi,\n ct: any,\n uid: string,\n rows: Array<Record<string, string>>,\n startRowNumber: number,\n options: {\n mode?: 'auto' | 'update' | 'create_or_override';\n publish?: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n user?: any;\n }\n): Promise<ProcessRowsStats> {\n const attrs = ct.attributes || {};\n const { mode = 'auto', publish = true, publishStrategy = 'safe', user } = options;\n const isDraftAndPublish = Boolean(ct.options?.draftAndPublish);\n\n const stats: ProcessRowsStats = {\n total: rows.length,\n created: 0,\n updated: 0,\n skipped: 0,\n newWithoutDocId: 0,\n errors: [],\n diffs: [],\n };\n\n for (let i = 0; i < rows.length; i++) {\n const rowNumber = startRowNumber + i;\n const row = rows[i];\n\n let docId = extractDocId(row);\n const rowLocale = extractLocale(row);\n\n // If singleType and no documentId provided in row, auto-detect existing single document\n if (ct.kind === 'singleType' && !docId) {\n try {\n const findSingleArgs: any = {};\n if (rowLocale) findSingleArgs.locale = rowLocale;\n const singleDoc = await (strapi.documents(uid as any) as any).findFirst(findSingleArgs);\n if (singleDoc?.documentId) {\n docId = singleDoc.documentId;\n }\n } catch {}\n }\n\n const payload = parseRowToPayload(strapi, attrs, row);\n\n try {\n if (mode === 'update') {\n if (!docId) {\n stats.skipped++;\n stats.errors.push({\n row: rowNumber,\n error: 'Missing or invalid documentId for Update mode. (Tip: Use Smart Auto-Detect mode to auto-add entries without document IDs).',\n });\n continue;\n }\n\n const existing = await findExistingDocument(strapi, uid, docId, rowLocale);\n\n if (!existing) {\n stats.skipped++;\n stats.errors.push({\n row: rowNumber,\n documentId: docId,\n error: `Document with ID \"${docId}\" not found in database.`,\n });\n continue;\n }\n\n const resolvedDocId = existing.documentId || docId;\n const mergedPayload = { ...payload };\n for (const key of Object.keys(payload)) {\n if (attrs[key]?.type === 'component' && typeof payload[key] === 'object' && payload[key] !== null) {\n mergedPayload[key] = deepMergeComponent((existing as any)[key], payload[key]);\n }\n }\n\n if (Object.keys(mergedPayload).length === 0) {\n stats.skipped++;\n stats.diffs.push({\n uid,\n collectionName: ct.info?.displayName || uid,\n documentId: resolvedDocId,\n label: (existing as any).title || (existing as any).name || `Entry #${resolvedDocId}`,\n attribute: '',\n oldValue: existing,\n newValue: {},\n status: 'skipped',\n message: `Skipped (no editable attributes in row ${rowNumber})`,\n });\n continue;\n }\n\n const updateArgs: any = {\n documentId: resolvedDocId,\n data: mergedPayload,\n };\n if (rowLocale) updateArgs.locale = rowLocale;\n\n await (strapi.documents(uid as any) as any).update(updateArgs);\n\n const isApproved = isDraftAndPublish && Boolean(existing?.publishedAt) && existing?.status !== 'modified';\n const shouldPublish = isDraftAndPublish && Boolean(publish) && (\n publishStrategy === 'all' || options.unreviewedConsent ? true : isApproved\n );\n\n if (shouldPublish) {\n try {\n const pubArgs: any = { documentId: resolvedDocId };\n if (rowLocale) pubArgs.locale = rowLocale;\n await (strapi.documents(uid as any) as any).publish(pubArgs);\n } catch (pubErr) {\n strapi.log.warn(`[bulk-updater] Auto-publish failed for ${resolvedDocId}:`, pubErr);\n }\n }\n\n try {\n await recordContentHistoryVersion(strapi, {\n uid,\n documentId: resolvedDocId,\n userId: user?.id,\n statusOverride: shouldPublish ? 'published' : (isDraftAndPublish ? 'draft' : undefined),\n });\n } catch {}\n\n stats.updated++;\n for (const attrKey of Object.keys(payload)) {\n const oldVal = (existing as any)?.[attrKey] ?? null;\n const newVal = payload[attrKey];\n stats.diffs.push({\n uid,\n collectionName: ct.info?.displayName || uid,\n documentId: resolvedDocId,\n label: (existing as any).title || (existing as any).name || `Entry #${resolvedDocId}`,\n attribute: attrKey,\n oldValue: oldVal,\n newValue: newVal,\n status: 'updated',\n message: `Updated \"${attrKey}\" via CSV import (row ${rowNumber})`,\n });\n }\n } else if (mode === 'create_or_override') {\n let existing: any = null;\n if (docId) {\n existing = await findExistingDocument(strapi, uid, docId, rowLocale);\n }\n\n if (existing) {\n const resolvedDocId = existing.documentId || docId;\n const mergedPayload = { ...payload };\n for (const key of Object.keys(payload)) {\n if (attrs[key]?.type === 'component' && typeof payload[key] === 'object' && payload[key] !== null) {\n mergedPayload[key] = deepMergeComponent((existing as any)[key], payload[key]);\n }\n }\n\n const updateArgs: any = {\n documentId: resolvedDocId,\n data: mergedPayload,\n };\n if (rowLocale) updateArgs.locale = rowLocale;\n\n await (strapi.documents(uid as any) as any).update(updateArgs);\n\n const isApproved = isDraftAndPublish && Boolean(existing?.publishedAt) && existing?.status !== 'modified';\n const shouldPublish = isDraftAndPublish && Boolean(publish) && (\n publishStrategy === 'all' || options.unreviewedConsent ? true : isApproved\n );\n\n if (shouldPublish) {\n try {\n const pubArgs: any = { documentId: resolvedDocId };\n if (rowLocale) pubArgs.locale = rowLocale;\n await (strapi.documents(uid as any) as any).publish(pubArgs);\n } catch (pubErr) {\n strapi.log.warn(`[bulk-updater] Auto-publish failed for ${resolvedDocId}:`, pubErr);\n }\n }\n\n try {\n await recordContentHistoryVersion(strapi, {\n uid,\n documentId: resolvedDocId,\n userId: user?.id,\n statusOverride: shouldPublish ? 'published' : (isDraftAndPublish ? 'draft' : undefined),\n });\n } catch {}\n\n stats.updated++;\n for (const attrKey of Object.keys(payload)) {\n const oldVal = (existing as any)?.[attrKey] ?? null;\n const newVal = payload[attrKey];\n stats.diffs.push({\n uid,\n collectionName: ct.info?.displayName || uid,\n documentId: resolvedDocId,\n label: (existing as any).title || (existing as any).name || `Entry #${resolvedDocId}`,\n attribute: attrKey,\n oldValue: oldVal,\n newValue: newVal,\n status: 'updated',\n message: `Overridden \"${attrKey}\" via CSV import (row ${rowNumber})`,\n });\n }\n continue;\n }\n\n const createArgs: any = { data: payload };\n if (rowLocale) createArgs.locale = rowLocale;\n const created: any = await strapi.documents(uid as any).create(createArgs);\n\n const newDocId = created?.documentId || docId;\n const shouldPublishNew = isDraftAndPublish && Boolean(publish) && (\n publishStrategy === 'all' || options.unreviewedConsent ? true : false\n );\n\n if (shouldPublishNew && newDocId) {\n try {\n const pubArgs: any = { documentId: newDocId };\n if (rowLocale) pubArgs.locale = rowLocale;\n await (strapi.documents(uid as any) as any).publish(pubArgs);\n } catch (pubErr) {\n strapi.log.warn(`[bulk-updater] Auto-publish failed for ${newDocId}:`, pubErr);\n }\n }\n\n try {\n await recordContentHistoryVersion(strapi, {\n uid,\n documentId: newDocId,\n userId: user?.id,\n statusOverride: shouldPublishNew ? 'published' : (isDraftAndPublish ? 'draft' : undefined),\n });\n } catch {}\n\n stats.created++;\n if (!docId) {\n stats.newWithoutDocId++;\n }\n for (const attrKey of Object.keys(payload)) {\n stats.diffs.push({\n uid,\n collectionName: ct.info?.displayName || uid,\n documentId: newDocId,\n label: created?.title || created?.name || `New Entry #${newDocId}`,\n attribute: attrKey,\n oldValue: null,\n newValue: payload[attrKey],\n status: 'created',\n message: docId\n ? `Created \"${attrKey}\" via CSV import (row ${rowNumber})`\n : `Created \"${attrKey}\" as new entry (row ${rowNumber})`,\n });\n }\n } else {\n // Default: Smart Auto-Detect ('auto')\n let existing: any = null;\n if (docId) {\n existing = await findExistingDocument(strapi, uid, docId, rowLocale);\n }\n\n if (existing) {\n const resolvedDocId = existing.documentId || docId;\n const mergedPayload = { ...payload };\n for (const key of Object.keys(payload)) {\n if (attrs[key]?.type === 'component' && typeof payload[key] === 'object' && payload[key] !== null) {\n mergedPayload[key] = deepMergeComponent((existing as any)[key], payload[key]);\n }\n }\n\n const updateArgs: any = {\n documentId: resolvedDocId,\n data: mergedPayload,\n };\n if (rowLocale) updateArgs.locale = rowLocale;\n\n await (strapi.documents(uid as any) as any).update(updateArgs);\n\n const isApproved = isDraftAndPublish && Boolean(existing?.publishedAt) && existing?.status !== 'modified';\n const shouldPublish = isDraftAndPublish && Boolean(publish) && (\n publishStrategy === 'all' || options.unreviewedConsent ? true : isApproved\n );\n\n if (shouldPublish) {\n try {\n const pubArgs: any = { documentId: resolvedDocId };\n if (rowLocale) pubArgs.locale = rowLocale;\n await (strapi.documents(uid as any) as any).publish(pubArgs);\n } catch (pubErr) {\n strapi.log.warn(`[bulk-updater] Auto-publish failed for ${resolvedDocId}:`, pubErr);\n }\n }\n\n try {\n await recordContentHistoryVersion(strapi, {\n uid,\n documentId: resolvedDocId,\n userId: user?.id,\n statusOverride: shouldPublish ? 'published' : (isDraftAndPublish ? 'draft' : undefined),\n });\n } catch {}\n\n stats.updated++;\n for (const attrKey of Object.keys(payload)) {\n const oldVal = (existing as any)?.[attrKey] ?? null;\n const newVal = payload[attrKey];\n stats.diffs.push({\n uid,\n collectionName: ct.info?.displayName || uid,\n documentId: resolvedDocId,\n label: (existing as any).title || (existing as any).name || `Entry #${resolvedDocId}`,\n attribute: attrKey,\n oldValue: oldVal,\n newValue: newVal,\n status: 'updated',\n message: `Updated \"${attrKey}\" via CSV import (row ${rowNumber})`,\n });\n }\n continue;\n }\n\n // Missing docId OR provided docId does not exist in DB -> create new\n const createArgs: any = { data: payload };\n if (rowLocale) createArgs.locale = rowLocale;\n const created: any = await strapi.documents(uid as any).create(createArgs);\n\n const newDocId = created?.documentId || docId;\n const shouldPublishNew = isDraftAndPublish && Boolean(publish) && (\n publishStrategy === 'all' || options.unreviewedConsent ? true : false\n );\n\n if (shouldPublishNew && newDocId) {\n try {\n const pubArgs: any = { documentId: newDocId };\n if (rowLocale) pubArgs.locale = rowLocale;\n await (strapi.documents(uid as any) as any).publish(pubArgs);\n } catch (pubErr) {\n strapi.log.warn(`[bulk-updater] Auto-publish failed for ${newDocId}:`, pubErr);\n }\n }\n\n try {\n await recordContentHistoryVersion(strapi, {\n uid,\n documentId: newDocId,\n userId: user?.id,\n statusOverride: shouldPublishNew ? 'published' : (isDraftAndPublish ? 'draft' : undefined),\n });\n } catch {}\n\n stats.created++;\n if (!docId) {\n stats.newWithoutDocId++;\n }\n for (const attrKey of Object.keys(payload)) {\n stats.diffs.push({\n uid,\n collectionName: ct.info?.displayName || uid,\n documentId: newDocId,\n label: created?.title || created?.name || `New Entry #${newDocId}`,\n attribute: attrKey,\n oldValue: null,\n newValue: payload[attrKey],\n status: 'created',\n message: docId\n ? `Created \"${attrKey}\" as new entry (documentId \"${docId}\" not found in database - row ${rowNumber})`\n : `Created \"${attrKey}\" as new entry (no documentId provided in CSV - row ${rowNumber})`,\n });\n }\n }\n } catch (err: any) {\n stats.errors.push({\n row: rowNumber,\n documentId: docId || undefined,\n error: extractDetailedErrorMessage(err),\n });\n }\n }\n\n return stats;\n}\n\nasync function recordCsvAuditLog(\n strapi: Core.Strapi,\n ct: any,\n uid: string,\n batchId: string,\n stats: { total: number; created: number; updated: number; skipped: number; diffs: Array<any> },\n user?: any,\n publishOnApproval?: boolean,\n publishStrategy?: 'safe' | 'all',\n unreviewedConsent?: boolean\n) {\n if (stats.updated === 0 && stats.created === 0) return;\n\n try {\n const auditService = strapi.plugin('bulk-updater').service('audit');\n if (!auditService) return;\n\n const isEnabled = typeof auditService.isAuditEnabled === 'function'\n ? auditService.isAuditEnabled()\n : Boolean(auditService.getAuditConfig?.().enabled ?? true);\n\n if (!isEnabled) return;\n\n const userEmail = user?.email || 'admin@strapi.io';\n const userName = user ? `${user.firstname || ''} ${user.lastname || ''}`.trim() : 'CSV Importer';\n const collectionDisplayName = ct.info?.displayName || uid;\n const updatedDiffs = stats.diffs.filter(\n (d) => d.status === 'updated' || d.status === 'created'\n );\n const uniqueAttributes = Array.from(\n new Set(updatedDiffs.map((d) => d.attribute))\n ).filter(Boolean);\n const attrListStr = uniqueAttributes.length > 0 ? uniqueAttributes.join(', ') : 'fields';\n\n const batchAttribute = `CSV [${collectionDisplayName}]: ${attrListStr}`;\n\n let batchValue = '';\n if (updatedDiffs.length === 1) {\n const d = updatedDiffs[0];\n const newStr = d.newValue !== null && d.newValue !== undefined ? String(d.newValue) : '(empty)';\n batchValue = `\"${d.label}\": ${d.attribute} → \"${newStr}\"`;\n } else if (updatedDiffs.length > 1 && stats.updated === 1 && stats.created === 0) {\n const d = updatedDiffs[0];\n const changes = updatedDiffs\n .map((ud) => `${ud.attribute}: \"${ud.newValue ?? ''}\"`)\n .join(', ');\n batchValue = `\"${d.label}\": ${changes}`;\n } else {\n const sampleVal = updatedDiffs[0]\n ? ` (e.g. ${updatedDiffs[0].attribute}: \"${updatedDiffs[0].newValue ?? ''}\")`\n : '';\n batchValue = `${stats.updated} updated, ${stats.created} created in ${collectionDisplayName}${sampleVal}`;\n }\n\n const batchSummary = {\n batchId,\n attribute: batchAttribute,\n value: batchValue,\n updatedCount: stats.updated + stats.created,\n skippedCount: stats.skipped,\n totalTargets: stats.total,\n };\n\n const userObj = {\n email: userEmail || 'admin@strapi.io',\n firstname: userName || 'Admin',\n };\n\n if (typeof auditService.recordBatch === 'function') {\n await auditService.recordBatch(\n batchSummary,\n stats.diffs,\n userObj,\n publishOnApproval,\n publishStrategy,\n unreviewedConsent\n );\n } else if (typeof auditService.logOperation === 'function') {\n await auditService.logOperation({\n ...batchSummary,\n userEmail,\n userName,\n diffs: stats.diffs,\n });\n }\n } catch (auditErr) {\n strapi.log.warn('[bulk-updater] Failed logging CSV import audit:', auditErr);\n }\n}\n\nexport default ({ strapi }: { strapi: Core.Strapi }) => ({\n /**\n * Generates a sample template CSV with schema attribute headers and sample values\n */\n async getTemplateCsv(uid: string) {\n const ct = strapi.contentTypes[uid];\n if (!ct) {\n throw new Error(`Content type ${uid} not found`);\n }\n\n const attrs = ct.attributes || {};\n const excluded = ['createdAt', 'updatedAt', 'publishedAt', 'createdBy', 'updatedBy', 'localizations'];\n\n // Base columns: documentId (optional for create, required for update)\n const headers = ['documentId'];\n const sampleRow: string[] = ['(Leave empty to create new, or enter existing docId)'];\n\n for (const [attrName, attrDef] of Object.entries(attrs) as any[]) {\n if (excluded.includes(attrName)) continue;\n if (attrDef.type === 'relation') continue;\n if (attrDef.type === 'component' || attrDef.type === 'dynamiczone') continue;\n\n headers.push(attrName);\n let sampleVal = '';\n switch (attrDef.type) {\n case 'string':\n case 'text':\n case 'richtext':\n sampleVal = `Sample ${attrName}`;\n break;\n case 'integer':\n case 'biginteger':\n case 'float':\n case 'decimal':\n sampleVal = '10';\n break;\n case 'boolean':\n sampleVal = 'true';\n break;\n case 'email':\n sampleVal = 'sample@example.com';\n break;\n case 'enumeration':\n sampleVal = attrDef.enum?.[0] || 'option1';\n break;\n case 'customField':\n sampleVal = 'value';\n break;\n default:\n sampleVal = 'sample';\n }\n sampleRow.push(sampleVal);\n }\n\n const csvContent =\n '\\uFEFF' +\n headers.map(escapeCsvValue).join(',') +\n '\\r\\n' +\n sampleRow.map(escapeCsvValue).join(',') +\n '\\r\\n';\n\n return {\n filename: `${ct.info?.singularName || 'template'}_template.csv`,\n csvContent,\n headers,\n };\n },\n\n /**\n * Exports entries of a collection to CSV with deep nested component support,\n * RFC-4180 CRLF line endings, and UTF-8 BOM for 100% Microsoft Excel compatibility.\n */\n async exportCollectionCsv(\n uid: string,\n options: {\n search?: string;\n attribute?: string;\n filterOperator?: string;\n filterQuery?: string;\n limit?: number;\n documentIds?: string[];\n } = {}\n ) {\n const ct = strapi.contentTypes[uid];\n if (!ct) {\n throw new Error(`Content type ${uid} not found`);\n }\n\n const allComponents = strapi.components || {};\n\n // 1. Discover all exportable fields, including nested components\n const fields = discoverExportFields(ct, allComponents);\n\n // 2. Build database query filters\n const filters: Record<string, any> = {};\n const { attribute, filterOperator, filterQuery, search, documentIds } = options;\n\n // Filter by specific selected document IDs if provided\n if (documentIds && Array.isArray(documentIds) && documentIds.length > 0) {\n filters.documentId = { $in: documentIds };\n }\n\n // Apply attribute condition filter with nested component support\n if (attribute && filterOperator && filterOperator !== 'none') {\n const isNested = attribute.includes('.');\n if (filterOperator === 'empty') {\n if (isNested) {\n const [parent, child] = attribute.split('.');\n filters[parent] = { [child]: { $null: true } };\n } else {\n filters[attribute] = { $null: true };\n }\n } else if (filterOperator === 'not_empty') {\n if (isNested) {\n const [parent, child] = attribute.split('.');\n filters[parent] = { [child]: { $notNull: true } };\n } else {\n filters[attribute] = { $notNull: true };\n }\n } else if (filterQuery !== undefined && filterQuery !== '') {\n const opMap: Record<string, string> = {\n equals: '$eq',\n notEquals: '$ne',\n contains: '$containsi',\n notContains: '$notContainsi',\n startsWith: '$startsWith',\n endsWith: '$endsWith',\n };\n const strapiOp = opMap[filterOperator] || '$eq';\n if (isNested) {\n const [parent, child] = attribute.split('.');\n filters[parent] = { [child]: { [strapiOp]: filterQuery } };\n } else {\n filters[attribute] = { [strapiOp]: filterQuery };\n }\n }\n }\n\n // Text search filter\n if (search && search.trim() !== '') {\n const q = search.trim();\n const searchConditions: any[] = [];\n const searchFields = ['name', 'title', 'email', 'slug', 'description'].filter(\n (f) => ct.attributes?.[f] && ['string', 'text', 'email'].includes(ct.attributes[f].type)\n );\n\n for (const field of searchFields) {\n searchConditions.push({ [field]: { $containsi: q } });\n }\n\n if (searchConditions.length > 0) {\n if (filters && Object.keys(filters).length > 0) {\n filters.$and = [{ $or: searchConditions }];\n } else {\n filters.$or = searchConditions;\n }\n }\n }\n\n // 3. Build deep populate tree so nested components and relations are retrieved\n const deepPopulate = buildDeepPopulate(ct.attributes || {}, allComponents);\n\n // 4. Retrieve entries and generate RFC-4180 CRLF rows with UTF-8 BOM\n const lines: string[] = [];\n lines.push(fields.map((f) => escapeCsvValue(f.key)).join(','));\n\n let totalExported = 0;\n const maxLimit = options.limit && options.limit > 0 ? options.limit : Infinity;\n const CHUNK_SIZE = 1000;\n\n if (ct.kind === 'singleType') {\n const findFirstArgs: any = {};\n if (deepPopulate) {\n findFirstArgs.populate = deepPopulate;\n }\n const doc = await (strapi.documents(uid as any) as any).findFirst(findFirstArgs);\n if (doc) {\n const rowValues = fields.map((f) => escapeCsvValue(getNestedExportValue(doc, f.key)));\n lines.push(rowValues.join(','));\n totalExported = 1;\n }\n } else {\n let currentPage = 1;\n let hasMore = true;\n\n while (hasMore && totalExported < maxLimit) {\n const remaining = maxLimit - totalExported;\n const currentBatchLimit = Math.min(CHUNK_SIZE, remaining);\n\n const findPageArgs: any = {\n filters: Object.keys(filters).length > 0 ? filters : undefined,\n page: currentPage,\n pageSize: currentBatchLimit,\n sort: { createdAt: 'desc' },\n };\n if (deepPopulate) {\n findPageArgs.populate = deepPopulate;\n }\n\n const chunkEntries: any[] = await (strapi.documents(uid as any) as any).findMany(findPageArgs);\n\n if (!chunkEntries || chunkEntries.length === 0) {\n hasMore = false;\n break;\n }\n\n for (const entry of chunkEntries) {\n const rowValues = fields.map((f) => escapeCsvValue(getNestedExportValue(entry, f.key)));\n lines.push(rowValues.join(','));\n totalExported++;\n if (totalExported >= maxLimit) {\n hasMore = false;\n break;\n }\n }\n\n if (chunkEntries.length < currentBatchLimit) {\n hasMore = false;\n } else {\n currentPage++;\n }\n }\n }\n\n // Prepend UTF-8 BOM and terminate lines with CRLF for seamless Excel import\n const csvContent = '\\uFEFF' + lines.join('\\r\\n') + '\\r\\n';\n const filename = `${ct.info?.singularName || uid}_export_${new Date().toISOString().slice(0, 10)}.csv`;\n\n return {\n filename,\n csvContent,\n count: totalExported,\n fields: fields.map((f) => f.key),\n };\n },\n\n /**\n * Exports violations of a specific rule directly into a CSV\n */\n async exportViolationsCsv(ruleId: string) {\n const validationRulesService = strapi.plugin('bulk-updater').service('validationRules');\n const scanReport = await validationRulesService.scanViolations(ruleId);\n\n const headers = [\n 'collectionUid',\n 'collectionName',\n 'documentId',\n 'entryLabel',\n 'targetField',\n 'violatingOption',\n 'foundCount',\n 'maxAllowed',\n 'directEditorUrl',\n ];\n\n const lines: string[] = [];\n lines.push(headers.map(escapeCsvValue).join(','));\n\n for (const v of scanReport.violations) {\n const row = [\n v.uid,\n v.collectionDisplayName,\n v.documentId,\n v.entryLabel,\n scanReport.rule.targetField,\n v.violatingOption,\n v.foundCount,\n v.maxAllowed,\n v.editUrl,\n ];\n lines.push(row.map(escapeCsvValue).join(','));\n }\n\n const safeRuleName = scanReport.rule.name.replace(/[^a-zA-Z0-9_-]/g, '_');\n const filename = `violations_${safeRuleName}_${new Date().toISOString().slice(0, 10)}.csv`;\n\n return {\n filename,\n csvContent: '\\uFEFF' + lines.join('\\r\\n') + '\\r\\n',\n count: scanReport.violations.length,\n ruleName: scanReport.rule.name,\n };\n },\n\n /**\n * Bulk Export: Exports selected entries across multiple collections or a multi-collection batch.\n */\n async exportBulkCsv(selectedEntries: Array<{ uid: string; documentId: string }>) {\n if (!selectedEntries || selectedEntries.length === 0) {\n throw new Error('No entries selected for bulk export');\n }\n\n // Group selected documentIds by collection uid\n const byUid: Record<string, string[]> = {};\n for (const item of selectedEntries) {\n if (!byUid[item.uid]) byUid[item.uid] = [];\n byUid[item.uid].push(item.documentId);\n }\n\n const uids = Object.keys(byUid);\n\n // If all entries belong to a single collection, export full collection schema with deep fields\n if (uids.length === 1) {\n const uid = uids[0];\n return await this.exportCollectionCsv(uid, { documentIds: byUid[uid], limit: 0 });\n }\n\n // Multi-collection unified export\n const rows: string[] = [];\n const headers = [\n 'Collection UID',\n 'Collection Name',\n 'Document ID',\n 'Record Title / Name',\n 'Primary Identifier',\n 'Created At',\n 'Updated At',\n 'Published Status',\n ];\n rows.push(headers.map(escapeCsvValue).join(','));\n\n let totalExported = 0;\n\n for (const uid of uids) {\n const ct = strapi.contentTypes[uid];\n if (!ct) continue;\n const displayName = ct.info?.displayName || uid;\n const docIds = byUid[uid];\n\n const entries = await (strapi.documents(uid as any) as any).findMany({\n filters: { documentId: { $in: docIds } },\n limit: docIds.length,\n });\n\n for (const entry of (entries || []) as any[]) {\n const titleOrName = entry.title || entry.name || entry.subject || entry.email || `Entry #${entry.documentId}`;\n const identifier = entry.slug || entry.email || entry.username || entry.documentId;\n const isPublished = Boolean(entry.publishedAt);\n\n const row = [\n uid,\n displayName,\n entry.documentId,\n titleOrName,\n identifier,\n entry.createdAt || '',\n entry.updatedAt || '',\n isPublished ? 'Published' : 'Draft',\n ];\n rows.push(row.map(escapeCsvValue).join(','));\n totalExported++;\n }\n }\n\n const filename = `bulk_export_selected_${totalExported}_entries_${new Date().toISOString().slice(0, 10)}.csv`;\n return {\n filename,\n csvContent: '\\uFEFF' + rows.join('\\r\\n') + '\\r\\n',\n count: totalExported,\n isMultiCollection: true,\n };\n },\n\n /**\n * Imports a single chunk of CSV rows (for large dataset streaming/batching).\n * Aggregates stats across chunks and writes unified audit trail on the final chunk.\n */\n async importChunk(\n uid: string,\n rows: Array<Record<string, string>>,\n options: {\n batchId?: string;\n isFirstChunk?: boolean;\n isLastChunk?: boolean;\n startRowNumber?: number;\n mode?: 'auto' | 'update' | 'create_or_override';\n publish?: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n user?: any;\n }\n ) {\n const ct = strapi.contentTypes[uid];\n if (!ct) {\n throw new Error(`Content type ${uid} not found`);\n }\n\n cleanupStaleSessions();\n\n const batchId = options.batchId || `csv_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n let session = csvImportSessions.get(batchId);\n\n if (!session || options.isFirstChunk) {\n session = {\n batchId,\n uid,\n createdAt: Date.now(),\n total: 0,\n created: 0,\n updated: 0,\n skipped: 0,\n newWithoutDocId: 0,\n errors: [],\n diffs: [],\n publishStrategy: options.publishStrategy,\n unreviewedConsent: options.unreviewedConsent,\n };\n csvImportSessions.set(batchId, session);\n }\n\n const startRowNumber = options.startRowNumber || (session.total + 2);\n const chunkStats = await processCsvRows(strapi, ct, uid, rows || [], startRowNumber, options);\n\n session.total += chunkStats.total;\n session.created += chunkStats.created;\n session.updated += chunkStats.updated;\n session.skipped += chunkStats.skipped;\n session.newWithoutDocId += chunkStats.newWithoutDocId;\n session.errors.push(...chunkStats.errors);\n session.diffs.push(...chunkStats.diffs);\n\n if (options.isLastChunk) {\n await recordCsvAuditLog(\n strapi,\n ct,\n uid,\n batchId,\n session,\n options.user,\n options.publish !== false,\n session.publishStrategy || options.publishStrategy,\n session.unreviewedConsent ?? options.unreviewedConsent\n );\n\n try {\n const bulkService = strapi.plugin('bulk-updater').service('bulkUpdater');\n if (bulkService && (bulkService as any).invalidateCollectionCache) {\n (bulkService as any).invalidateCollectionCache(uid);\n }\n } catch {}\n\n const aggregateStats = {\n total: session.total,\n created: session.created,\n updated: session.updated,\n skipped: session.skipped,\n newWithoutDocId: session.newWithoutDocId,\n errors: session.errors,\n diffs: session.diffs,\n };\n\n csvImportSessions.delete(batchId);\n\n return {\n success: true,\n batchId,\n chunkStats,\n stats: aggregateStats,\n isFinished: true,\n };\n }\n\n return {\n success: true,\n batchId,\n chunkStats,\n isFinished: false,\n };\n },\n\n /**\n * Imports CSV records to update existing records or insert/override records (single payload).\n */\n async importCsv(\n uid: string,\n csvText: string,\n options: {\n mode?: 'auto' | 'update' | 'create_or_override';\n publish?: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n user?: any;\n }\n ) {\n const ct = strapi.contentTypes[uid];\n if (!ct) {\n throw new Error(`Content type ${uid} not found`);\n }\n\n const parsedRows = parseCsv(csvText);\n if (!parsedRows || parsedRows.length === 0) {\n throw new Error('CSV is empty or could not be parsed.');\n }\n\n const batchId = `csv_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const stats = await processCsvRows(strapi, ct, uid, parsedRows, 2, options);\n\n try {\n const bulkService = strapi.plugin('bulk-updater').service('bulkUpdater');\n if (bulkService && (bulkService as any).invalidateCollectionCache) {\n (bulkService as any).invalidateCollectionCache(uid);\n }\n } catch {}\n\n await recordCsvAuditLog(\n strapi,\n ct,\n uid,\n batchId,\n stats,\n options.user,\n options.publish !== false,\n options.publishStrategy,\n options.unreviewedConsent\n );\n\n return {\n success: true,\n batchId,\n stats,\n };\n },\n\n /**\n * Executes a pending CSV batch approved by Checker or queued for off-peak execution\n */\n async executeCsvPendingBatch(\n uid: string,\n rows: Array<Record<string, string>>,\n batchId: string,\n options: {\n mode?: 'auto' | 'update' | 'create_or_override';\n publish?: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n user?: any;\n } = {},\n checkerUser?: any\n ) {\n const ct = strapi.contentTypes[uid];\n if (!ct) {\n throw new Error(`Content type ${uid} not found`);\n }\n\n const effectiveUser = checkerUser || options.user;\n const stats = await processCsvRows(strapi, ct, uid, rows || [], 2, {\n ...options,\n user: effectiveUser,\n });\n\n await recordCsvAuditLog(\n strapi,\n ct,\n uid,\n batchId,\n stats,\n effectiveUser,\n options.publish !== false,\n options.publishStrategy,\n options.unreviewedConsent\n );\n\n try {\n const bulkService = strapi.plugin('bulk-updater').service('bulkUpdater');\n if (bulkService && (bulkService as any).invalidateCollectionCache) {\n (bulkService as any).invalidateCollectionCache(uid);\n }\n } catch {}\n\n return {\n success: true,\n batchId,\n stats,\n };\n },\n\n /**\n * Pre-Flight Dry-Run Validation: Non-mutating analysis verifying document existence,\n * data types, schema integrity, and quota rule violations before execution.\n */\n async validatePreflight(\n uid: string,\n rows: Array<Record<string, string>>,\n options: {\n mode?: 'auto' | 'update' | 'create_or_override';\n } = {}\n ) {\n const ct = strapi.contentTypes[uid];\n if (!ct) {\n throw new Error(`Content type ${uid} not found`);\n }\n\n const { mode = 'auto' } = options;\n const attrs = ct.attributes || {};\n\n let validationRulesService: any = null;\n let activeRules: any[] = [];\n try {\n validationRulesService = strapi.plugin('bulk-updater').service('validationRules');\n if (validationRulesService) {\n const rulesRes = await validationRulesService.getRules();\n activeRules = (rulesRes || []).filter((r: any) => r.enabled);\n }\n } catch {}\n\n let validRows = 0;\n let estimatedUpdates = 0;\n let estimatedCreates = 0;\n const isDraftAndPublish = Boolean(ct.options?.draftAndPublish);\n const lifecycleStats = {\n isDraftAndPublish,\n totalChecked: 0,\n published: 0,\n modified: 0,\n draft: 0,\n unreviewedCount: 0,\n };\n const errors: Array<{ row: number; documentId?: string; error: string }> = [];\n const warnings: Array<{ row: number; documentId?: string; warning: string }> = [];\n\n for (let i = 0; i < rows.length; i++) {\n const rowNumber = i + 2;\n const row = rows[i];\n const docId = extractDocId(row);\n const rowLocale = extractLocale(row);\n let rowHasError = false;\n\n // 1. Document Existence Check\n let existing: any = null;\n if (docId) {\n existing = await findExistingDocument(strapi, uid, docId, rowLocale);\n }\n\n if (existing && isDraftAndPublish) {\n lifecycleStats.totalChecked++;\n const isApproved = Boolean(existing.publishedAt) && existing.status !== 'modified';\n if (isApproved) {\n lifecycleStats.published++;\n } else if (existing.status === 'modified') {\n lifecycleStats.modified++;\n lifecycleStats.unreviewedCount++;\n } else {\n lifecycleStats.draft++;\n lifecycleStats.unreviewedCount++;\n }\n }\n\n if (mode === 'update') {\n if (!docId) {\n errors.push({\n row: rowNumber,\n error: 'Missing or invalid documentId for Update Only mode.',\n });\n rowHasError = true;\n } else if (!existing) {\n errors.push({\n row: rowNumber,\n documentId: docId,\n error: `Document with ID \"${docId}\" not found in database.`,\n });\n rowHasError = true;\n } else {\n estimatedUpdates++;\n }\n } else if (mode === 'create_or_override') {\n if (existing) {\n estimatedUpdates++;\n } else {\n estimatedCreates++;\n }\n } else {\n // Smart Auto-Detect\n if (existing) {\n estimatedUpdates++;\n } else {\n estimatedCreates++;\n if (docId) {\n warnings.push({\n row: rowNumber,\n documentId: docId,\n warning: `Document ID \"${docId}\" not found in DB; will create as a new entry.`,\n });\n }\n }\n }\n\n // 2. Schema Type Validation\n for (const [colKey, rawVal] of Object.entries(row)) {\n if (!rawVal || rawVal.trim() === '') continue;\n const normalizedKey = colKey.toLowerCase().replace(/[\\s_-]/g, '');\n if (SYSTEM_FIELD_KEYS.has(normalizedKey)) continue;\n\n let attrDef = attrs[colKey];\n if (!attrDef && !colKey.includes('.')) {\n const matchKey = Object.keys(attrs).find(\n (k) => k.toLowerCase() === colKey.toLowerCase() || k.toLowerCase() === colKey.toLowerCase().replace(/\\s+/g, '')\n );\n if (matchKey) attrDef = attrs[matchKey];\n }\n\n if (attrDef) {\n if (attrDef.type === 'integer' || attrDef.type === 'biginteger') {\n const num = parseInt(rawVal, 10);\n if (isNaN(num)) {\n errors.push({\n row: rowNumber,\n documentId: docId || undefined,\n error: `Column \"${colKey}\" expects an integer, received: \"${rawVal}\"`,\n });\n rowHasError = true;\n }\n } else if (attrDef.type === 'float' || attrDef.type === 'decimal') {\n const num = parseFloat(rawVal);\n if (isNaN(num)) {\n errors.push({\n row: rowNumber,\n documentId: docId || undefined,\n error: `Column \"${colKey}\" expects a numeric float/decimal, received: \"${rawVal}\"`,\n });\n rowHasError = true;\n }\n } else if (attrDef.type === 'enumeration' && Array.isArray(attrDef.enum)) {\n if (!attrDef.enum.includes(rawVal.trim())) {\n warnings.push({\n row: rowNumber,\n documentId: docId || undefined,\n warning: `Column \"${colKey}\" value \"${rawVal}\" is not in defined enum options: [${attrDef.enum.join(', ')}]`,\n });\n }\n } else if (attrDef.type === 'json') {\n try {\n JSON.parse(rawVal);\n } catch {\n warnings.push({\n row: rowNumber,\n documentId: docId || undefined,\n warning: `Column \"${colKey}\" is type JSON but contains non-JSON text.`,\n });\n }\n }\n }\n\n // 3. Quota Rules Scan\n if (activeRules.length > 0) {\n for (const rule of activeRules) {\n if (rule.collectionUid && rule.collectionUid !== '*' && rule.collectionUid !== uid) continue;\n if (rule.includeRichTextHtml && (rawVal.includes('<h') || rawVal.includes('# '))) {\n const headings = extractHeadingsFromRichText(rawVal);\n for (const [tag, count] of Object.entries(headings)) {\n const max = rule.quotas?.[tag.toLowerCase()];\n if (max !== undefined && count > max) {\n warnings.push({\n row: rowNumber,\n documentId: docId || undefined,\n warning: `Rule \"${rule.name}\" quota warning: column \"${colKey}\" contains ${count} \"${tag.toUpperCase()}\" headings (maximum allowed: ${max}).`,\n });\n }\n }\n }\n }\n }\n }\n\n if (!rowHasError) {\n validRows++;\n }\n }\n\n return {\n success: true,\n totalRows: rows.length,\n validRows,\n estimatedUpdates,\n estimatedCreates,\n lifecycleStats,\n hasErrors: errors.length > 0,\n hasWarnings: warnings.length > 0,\n errors: errors.slice(0, 100),\n warnings: warnings.slice(0, 100),\n totalErrorCount: errors.length,\n totalWarningCount: warnings.length,\n };\n },\n\n /**\n * Previews CSV batch changes item-by-item without mutating the database.\n * Compares proposed CSV rows against existing documents to compute exact diffs for Maker-Checker review.\n */\n async previewCsvBatch(\n uid: string,\n rows: Array<Record<string, string>>,\n options: {\n mode?: 'auto' | 'update' | 'create_or_override';\n publish?: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n } = {}\n ) {\n const ct = strapi.contentTypes[uid];\n if (!ct) {\n throw new Error(`Content type \"${uid}\" not found`);\n }\n\n const attrs = ct.attributes || {};\n const { mode = 'auto' } = options;\n\n const diffs: any[] = [];\n let willUpdateCount = 0;\n let willCreateCount = 0;\n let unchangedCount = 0;\n let skippedCount = 0;\n\n for (let i = 0; i < rows.length; i++) {\n const rowNumber = i + 2;\n const row = rows[i];\n let docId = extractDocId(row);\n const rowLocale = extractLocale(row);\n\n // Handle singleType\n if (ct.kind === 'singleType' && !docId) {\n try {\n const findSingleArgs: any = {};\n if (rowLocale) findSingleArgs.locale = rowLocale;\n const singleDoc = await (strapi.documents(uid as any) as any).findFirst(findSingleArgs);\n if (singleDoc?.documentId) {\n docId = singleDoc.documentId;\n }\n } catch {}\n }\n\n // Check existing document\n let existing: any = null;\n if (docId) {\n existing = await findExistingDocument(strapi, uid, docId, rowLocale);\n }\n\n if (mode === 'update' && (!docId || !existing)) {\n skippedCount++;\n diffs.push({\n uid,\n collectionName: ct.info?.displayName || uid,\n documentId: docId || `(Row #${rowNumber})`,\n label: `Row #${rowNumber}`,\n attribute: '(record)',\n oldValue: null,\n newValue: null,\n oldDisplay: '—',\n newDisplay: '—',\n hasChange: false,\n status: 'will_skip',\n action: 'skip',\n message: !docId ? 'Missing documentId in update mode' : `Document \"${docId}\" not found in database`,\n });\n continue;\n }\n\n const payload = parseRowToPayload(strapi, attrs, row);\n\n if (existing) {\n const resolvedDocId = existing.documentId || docId;\n const entryLabel = existing.title || existing.name || existing.slug || `Entry #${resolvedDocId}`;\n let rowHasChanges = false;\n const payloadKeys = Object.keys(payload);\n\n if (payloadKeys.length === 0) {\n unchangedCount++;\n diffs.push({\n uid,\n collectionName: ct.info?.displayName || uid,\n documentId: resolvedDocId,\n label: entryLabel,\n attribute: '(no fields)',\n oldValue: null,\n newValue: null,\n oldDisplay: '—',\n newDisplay: '—',\n hasChange: false,\n status: 'unchanged',\n action: 'update',\n message: 'No modified attributes in CSV row',\n });\n } else {\n for (const attrKey of payloadKeys) {\n const oldVal = (existing as any)?.[attrKey] ?? null;\n let newVal = payload[attrKey];\n if (attrs[attrKey]?.type === 'component' && typeof newVal === 'object' && newVal !== null) {\n newVal = deepMergeComponent((existing as any)[attrKey], newVal);\n }\n\n const oldDisplay = formatValueDisplay(oldVal);\n const newDisplay = formatValueDisplay(newVal);\n const hasChange = String(oldVal ?? '') !== String(newVal ?? '');\n\n if (hasChange) {\n rowHasChanges = true;\n }\n\n diffs.push({\n uid,\n collectionName: ct.info?.displayName || uid,\n documentId: resolvedDocId,\n label: entryLabel,\n attribute: attrKey,\n oldValue: oldVal,\n newValue: newVal,\n oldDisplay,\n newDisplay,\n hasChange,\n status: hasChange ? 'will_update' : 'unchanged',\n action: 'update',\n message: hasChange ? `Will update \"${attrKey}\" from CSV` : `Already matches CSV value`,\n });\n }\n\n if (rowHasChanges) {\n willUpdateCount++;\n } else {\n unchangedCount++;\n }\n }\n } else {\n // New record to create\n willCreateCount++;\n const resolvedDocId = docId || `(Auto-generated)`;\n const entryLabel = payload.title || payload.name || payload.slug || `New Entry (Row #${rowNumber})`;\n const payloadKeys = Object.keys(payload);\n\n if (payloadKeys.length === 0) {\n diffs.push({\n uid,\n collectionName: ct.info?.displayName || uid,\n documentId: resolvedDocId,\n label: entryLabel,\n attribute: '(all fields)',\n oldValue: null,\n newValue: null,\n oldDisplay: '(new entry)',\n newDisplay: '(empty record)',\n hasChange: true,\n status: 'will_create',\n action: 'create',\n message: 'Will create new record',\n });\n } else {\n for (const attrKey of payloadKeys) {\n const newVal = payload[attrKey];\n diffs.push({\n uid,\n collectionName: ct.info?.displayName || uid,\n documentId: resolvedDocId,\n label: entryLabel,\n attribute: attrKey,\n oldValue: null,\n newValue: newVal,\n oldDisplay: '(new entry)',\n newDisplay: formatValueDisplay(newVal),\n hasChange: true,\n status: 'will_create',\n action: 'create',\n message: `Will create new record with attribute \"${attrKey}\"`,\n });\n }\n }\n }\n }\n\n return {\n success: true,\n summary: {\n total: rows.length,\n willUpdate: willUpdateCount,\n willCreate: willCreateCount,\n unchanged: unchangedCount,\n skipped: skippedCount,\n },\n diffs,\n };\n },\n\n /**\n * Submits a CSV batch with Guardrails: Maker-Checker (4-Eyes), Execution Windows, Off-Peak Scheduling\n */\n async submitBatch(\n uid: string,\n rows: Array<Record<string, string>>,\n options: {\n executionMode?: 'immediate' | 'queue_offpeak' | 'maker_checker';\n makerNotes?: string;\n forceImmediate?: boolean;\n mode?: 'auto' | 'update' | 'create_or_override';\n publish?: boolean;\n publishStrategy?: 'safe' | 'all';\n unreviewedConsent?: boolean;\n unreviewedCount?: number;\n user?: any;\n } = {}\n ) {\n const ct = strapi.contentTypes[uid];\n if (!ct) {\n throw new Error(`Content type ${uid} not found`);\n }\n\n if (!rows || rows.length === 0) {\n throw new Error('No CSV records provided for batch submission.');\n }\n\n const {\n executionMode = 'immediate',\n makerNotes = '',\n forceImmediate = false,\n mode = 'auto',\n publish = true,\n publishStrategy = 'safe',\n unreviewedConsent = false,\n unreviewedCount = 0,\n user,\n } = options;\n\n const executionConfig = getExecutionWindowConfig(strapi);\n const { isBusinessHours, policyMessage } = checkBusinessHours(executionConfig);\n const collectionDisplayName = ct.info?.displayName || uid;\n\n // 1. Enterprise Maker-Checker Flow (4-Eyes Approval Principle)\n if (executionMode === 'maker_checker') {\n const batchId = `csv_batch_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const batch: PendingBatch = {\n id: batchId,\n createdAt: new Date().toISOString(),\n createdBy: user\n ? {\n id: user.id,\n email: user.email,\n firstname: user.firstname,\n lastname: user.lastname,\n username: user.username,\n }\n : { email: 'admin@system.local' },\n payload: {\n action: 'csv_import',\n uid,\n rows,\n options: {\n mode,\n publish,\n publishStrategy,\n unreviewedConsent,\n user,\n },\n attribute: `CSV Import: ${collectionDisplayName}`,\n value: `${rows.length} rows (${mode} mode)`,\n publishOnApproval: publish,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n },\n summary: {\n attribute: `CSV Import: ${collectionDisplayName}`,\n value: `${rows.length} rows (${mode} mode)`,\n totalTargets: rows.length,\n collectionBreakdown: { [collectionDisplayName]: rows.length },\n publishOnApproval: publish,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n },\n status: 'pending_approval',\n executionMode: 'maker_checker',\n makerNotes,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n };\n\n registerPendingBatch(batch, {\n id: batchId,\n createdAt: batch.createdAt,\n createdBy: batch.createdBy,\n status: 'pending_approval',\n executionMode: 'maker_checker',\n attribute: `CSV Import: ${collectionDisplayName}`,\n value: `${rows.length} rows (${mode} mode)`,\n totalTargets: rows.length,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: publish,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n makerNotes,\n results: [],\n });\n\n return {\n success: true,\n pending: true,\n batchId,\n status: 'pending_approval',\n message: 'CSV batch submitted for Checker authorization (4-Eyes Maker-Checker Workflow).',\n batch,\n };\n }\n\n // 2. Off-Peak Queued Batch\n if (executionMode === 'queue_offpeak') {\n const batchId = `csv_batch_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const batch: PendingBatch = {\n id: batchId,\n createdAt: new Date().toISOString(),\n createdBy: user\n ? {\n id: user.id,\n email: user.email,\n firstname: user.firstname,\n lastname: user.lastname,\n username: user.username,\n }\n : { email: 'admin@system.local' },\n payload: {\n action: 'csv_import',\n uid,\n rows,\n options: {\n mode,\n publish,\n publishStrategy,\n unreviewedConsent,\n user,\n },\n attribute: `CSV Import: ${collectionDisplayName}`,\n value: `${rows.length} rows (${mode} mode)`,\n publishOnApproval: publish,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n },\n summary: {\n attribute: `CSV Import: ${collectionDisplayName}`,\n value: `${rows.length} rows (${mode} mode)`,\n totalTargets: rows.length,\n collectionBreakdown: { [collectionDisplayName]: rows.length },\n publishOnApproval: publish,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n },\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n makerNotes,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n };\n\n registerPendingBatch(batch, {\n id: batchId,\n createdAt: batch.createdAt,\n createdBy: batch.createdBy,\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n attribute: `CSV Import: ${collectionDisplayName}`,\n value: `${rows.length} rows (${mode} mode)`,\n totalTargets: rows.length,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: publish,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n makerNotes,\n results: [],\n });\n\n return {\n success: true,\n pending: true,\n batchId,\n status: 'queued_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n message: `CSV batch queued for server off-peak maintenance window (${executionConfig.offPeakStartTime}).`,\n batch,\n };\n }\n\n // 3. Peak Business Hours Restriction Active (Auto-Queue)\n if (executionConfig.enabled && executionConfig.autoQueueDuringBusinessHours && isBusinessHours && !forceImmediate) {\n const batchId = `csv_batch_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n const batch: PendingBatch = {\n id: batchId,\n createdAt: new Date().toISOString(),\n createdBy: user\n ? {\n id: user.id,\n email: user.email,\n firstname: user.firstname,\n lastname: user.lastname,\n username: user.username,\n }\n : { email: 'admin@system.local' },\n payload: {\n action: 'csv_import',\n uid,\n rows,\n options: {\n mode,\n publish,\n publishStrategy,\n unreviewedConsent,\n user,\n },\n attribute: `CSV Import: ${collectionDisplayName}`,\n value: `${rows.length} rows (${mode} mode)`,\n publishOnApproval: publish,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n },\n summary: {\n attribute: `CSV Import: ${collectionDisplayName}`,\n value: `${rows.length} rows (${mode} mode)`,\n totalTargets: rows.length,\n collectionBreakdown: { [collectionDisplayName]: rows.length },\n publishOnApproval: publish,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n },\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n makerNotes: 'Automatically queued due to peak business hours restriction.',\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n };\n\n registerPendingBatch(batch, {\n id: batchId,\n createdAt: batch.createdAt,\n createdBy: batch.createdBy,\n status: 'queued_offpeak',\n executionMode: 'queue_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n attribute: `CSV Import: ${collectionDisplayName}`,\n value: `${rows.length} rows (${mode} mode)`,\n totalTargets: rows.length,\n processedCount: 0,\n updatedCount: 0,\n skippedCount: 0,\n failedCount: 0,\n isLive: false,\n publishOnApproval: publish,\n publishStrategy,\n unreviewedConsent,\n unreviewedCount,\n policyMessage,\n makerNotes: 'Automatically queued due to peak business hours restriction.',\n results: [],\n });\n\n return {\n success: true,\n pending: true,\n batchId,\n status: 'queued_offpeak',\n scheduledFor: executionConfig.offPeakStartTime,\n message: policyMessage,\n batch,\n };\n }\n\n // 4. Immediate execution allowed: Signal frontend to proceed with chunked execution\n return {\n success: true,\n pending: false,\n executeNow: true,\n };\n },\n});\n","import routes from './routes';\nimport contentTypes from './content-types';\nimport bulkUpdaterController from './controllers/bulk-updater';\nimport auditController from './controllers/audit';\nimport validationRulesController from './controllers/validation-rules';\nimport csvController from './controllers/csv';\nimport bulkUpdaterService from './services/bulk-updater';\nimport auditService from './services/audit';\nimport validationRulesService, { extractHeadingsFromRichText, matchesPath, cleanKey } from './services/validation-rules';\nimport csvService from './services/csv';\nimport contentHistoryService, { recordContentHistoryVersion } from './services/content-history';\n\nimport { errors } from '@strapi/utils';\n\nfunction createValidationError(ruleName: string, detailMsg: string, targetField: string) {\n const fullMessage = `Validation Error (${ruleName}): ${detailMsg}`;\n const ApplicationErrorClass: any = (errors as any)?.ApplicationError || Error;\n\n const err = new ApplicationErrorClass(fullMessage);\n err.name = 'ApplicationError';\n err.status = 400;\n (err as any).isQuotaViolation = true;\n (err as any).targetField = targetField;\n (err as any).details = {};\n return err;\n}\n\nexport default {\n register({ strapi }: { strapi: any }) {\n // Register the server definition for custom field plugin::bulk-updater.scoped-select\n strapi.customFields.register({\n name: 'scoped-select',\n plugin: 'bulk-updater',\n type: 'string',\n });\n },\n bootstrap({ strapi }: { strapi: any }) {\n // Intercept quota validation errors to return HTTP 400 ApplicationError so Strapi's admin UI displays specific danger banner\n strapi.server.use(async (ctx: any, next: any) => {\n try {\n await next();\n } catch (err: any) {\n const isQuotaErr =\n err?.isQuotaViolation ||\n err?.name === 'ApplicationError' ||\n err?.name === 'ValidationError' ||\n (typeof err?.message === 'string' &&\n (err.message.startsWith('Validation Error') || err.message.includes('cannot appear more than')));\n\n if (isQuotaErr) {\n ctx.status = 400;\n ctx.body = {\n data: null,\n error: {\n status: 400,\n name: 'ApplicationError',\n message: err.message,\n details: {},\n },\n };\n return;\n }\n throw err;\n }\n });\n\n // Register Document Service middleware to enforce cross-component quotas on the backend\n strapi.documents.use(async (context: any, next: any) => {\n const params = context.params as any;\n if (['create', 'update'].includes(context.action)) {\n const data = params?.data;\n\n if (data && typeof data === 'object') {\n // 1. Fetch active UI-configured validation rules from the plugin store\n let activeUiRules: any[] = [];\n try {\n const rulesService = strapi.plugin('bulk-updater').service('validationRules');\n if (rulesService) {\n const allRules = await rulesService.getRules();\n activeUiRules = allRules.filter((r: any) => r.enabled);\n }\n } catch (err) {\n strapi.log.warn('[bulk-updater] Failed to fetch active UI validation rules:', err);\n }\n\n // 2. Discover attributes from schemas as fallback if not in UI rules\n // Filter UI rules scoped to this collection type (or '*' for global, with flexible UID / name matching)\n const effectiveRules: Array<{\n id: string;\n name: string;\n collectionUid?: string;\n targetField: string;\n quotas: Record<string, number>;\n includeRichTextHtml?: boolean;\n richTextFields?: string[];\n }> = [\n ...activeUiRules\n .filter((r: any) => {\n if (!r.collectionUid || r.collectionUid === '*') return true;\n if (r.collectionUid === context.uid) return true;\n const cleanRuleCol = cleanKey(r.collectionUid);\n const cleanCtxCol = cleanKey(context.uid);\n return cleanCtxCol.includes(cleanRuleCol) || cleanRuleCol.includes(cleanCtxCol);\n })\n .map((r: any) => ({\n id: r.id || r.targetField,\n name: r.name || r.targetField,\n collectionUid: r.collectionUid || '*',\n targetField: r.targetField,\n quotas: r.quotas || {},\n includeRichTextHtml: Boolean(r.includeRichTextHtml),\n richTextFields: r.richTextFields || [],\n })),\n ];\n\n const allComponents = strapi.components || {};\n for (const comp of Object.values(allComponents) as any[]) {\n const attrs = comp.attributes || {};\n for (const [attrName, attrDef] of Object.entries(attrs) as any[]) {\n if (\n attrDef.type === 'customField' &&\n (attrDef.customField === 'plugin::bulk-updater.scoped-select' ||\n attrDef.customField === 'global::scoped-select') &&\n !effectiveRules.some((r) => matchesPath(attrName, attrName, r.targetField))\n ) {\n const quotas = attrDef.options?.quotas || {};\n const items = attrDef.options?.items || [];\n const itemQuotas: Record<string, number> = {};\n\n for (const item of items) {\n if (typeof item.maxAllowed === 'number' && item.maxAllowed > 0) {\n itemQuotas[item.value] = item.maxAllowed;\n }\n }\n\n effectiveRules.push({\n id: `schema_${attrName}`,\n name: `${attrName} quota rule`,\n collectionUid: '*',\n targetField: attrName,\n quotas: {\n h1: 1,\n h2: 3,\n ...itemQuotas,\n ...quotas,\n },\n includeRichTextHtml: true,\n richTextFields: [],\n });\n }\n }\n }\n\n const structuredCounts: Record<string, Record<string, number>> = {};\n const richTextCounts: Record<string, number> = { h1: 0, h2: 0, h3: 0, h4: 0, h5: 0, h6: 0 };\n\n function scanDataTree(obj: any, currentPath = '') {\n if (!obj || typeof obj !== 'object') return;\n const compName = typeof obj.__component === 'string' ? obj.__component : '';\n\n for (const key of Object.keys(obj)) {\n if (key === '__component') continue;\n const val = obj[key];\n const newPath = currentPath ? `${currentPath}.${key}` : key;\n const normalizedPath = newPath.replace(/\\.\\d+/g, '');\n\n const compPath = compName\n ? (currentPath ? `${currentPath}.${compName}.${key}` : `${compName}.${key}`).replace(/\\.\\d+/g, '')\n : '';\n\n // Check structured rules matching targetField (supports dot notation like st-featured.titleHeadingStyle.titleStyle or titleHeadingStyle.titleStyle)\n for (const rule of effectiveRules) {\n const isMatch = matchesPath(normalizedPath, key, rule.targetField) ||\n (compPath ? matchesPath(compPath, key, rule.targetField) : false);\n\n if (isMatch && typeof val === 'string' && val.trim()) {\n const lowerVal = val.toLowerCase().trim();\n structuredCounts[rule.id] = structuredCounts[rule.id] || {};\n structuredCounts[rule.id][lowerVal] = (structuredCounts[rule.id][lowerVal] || 0) + 1;\n }\n }\n\n // Check rich text HTML / Markdown / Blocks content\n if (typeof val === 'string' && (val.includes('<h') || val.includes('#'))) {\n const headings = extractHeadingsFromRichText(val);\n for (const [tag, count] of Object.entries(headings)) {\n if (count > 0) {\n richTextCounts[tag] = (richTextCounts[tag] || 0) + count;\n }\n }\n } else if (Array.isArray(val) && val.length > 0 && typeof val[0] === 'object' && val[0]?.type) {\n // Strapi Blocks array\n const headings = extractHeadingsFromRichText(val);\n for (const [tag, count] of Object.entries(headings)) {\n if (count > 0) {\n richTextCounts[tag] = (richTextCounts[tag] || 0) + count;\n }\n }\n continue;\n }\n\n if (typeof val === 'object' && val !== null) {\n scanDataTree(val, newPath);\n }\n }\n }\n\n // If updating an existing document, merge incoming data with existing document\n // state so cross-component dynamic zone quotas are evaluated across the full tree\n let dataToScan = data;\n if (context.action === 'update' && (params?.documentId || params?.where?.documentId)) {\n const docId = params?.documentId || params?.where?.documentId;\n if (context.uid && docId) {\n try {\n const existing = await strapi.db?.query?.(context.uid)?.findOne?.({\n where: { documentId: docId },\n populate: true,\n });\n if (existing) {\n dataToScan = { ...existing, ...data };\n }\n } catch {\n // If lookup fails, scan incoming payload\n }\n }\n }\n\n scanDataTree(dataToScan);\n\n // Validate collected counts against active quotas\n for (const rule of effectiveRules) {\n const ruleCounts = structuredCounts[rule.id] || {};\n\n for (const [quotaKey, maxAllowed] of Object.entries(rule.quotas || {})) {\n const lowerVal = quotaKey.toLowerCase().trim();\n const structCount = ruleCounts[lowerVal] || 0;\n const rtCount = rule.includeRichTextHtml ? (richTextCounts[lowerVal] || 0) : 0;\n const totalFound = structCount + rtCount;\n\n if (totalFound > (maxAllowed as number)) {\n let detailMsg = `Option \"${quotaKey.toUpperCase()}\" cannot appear more than ${maxAllowed} time(s) across this entry.`;\n if (rtCount > 0 && structCount > 0) {\n detailMsg += ` Found ${totalFound} occurrences combined: ${structCount} in structured component ('${rule.targetField}') and ${rtCount} in rich text HTML / Markdown.`;\n } else if (rtCount > 0) {\n detailMsg += ` Found ${totalFound} in rich text HTML / Markdown content.`;\n } else {\n detailMsg += ` Found ${totalFound} in structured field '${rule.targetField}'.`;\n }\n throw createValidationError(rule.name, detailMsg, rule.targetField);\n }\n }\n }\n }\n }\n\n const result = await next();\n return result;\n });\n\n // Register universal Content History fallback middleware so Content History\n // operates reliably across all Strapi tiers (Community Edition and Enterprise)\n strapi.server.use(async (ctx: any, next: any) => {\n if (!ctx.path.startsWith('/content-manager/history-versions')) {\n await next();\n return;\n }\n\n await next();\n\n if (ctx.status === 404 || ctx.status === 405) {\n if (ctx.method === 'GET' && ctx.path === '/content-manager/history-versions') {\n const { contentType, documentId, locale, page = 1, pageSize = 20 } = ctx.query;\n if (!contentType) return;\n const historyQuery = strapi.db?.query?.('plugin::content-manager.history-version');\n if (!historyQuery) return;\n\n const pageNum = Math.max(1, parseInt(page, 10) || 1);\n const limit = Math.min(100, Math.max(1, parseInt(pageSize, 10) || 20));\n\n const whereClause: any = {\n contentType,\n ...(documentId ? { relatedDocumentId: documentId } : {}),\n ...(locale ? { locale } : {}),\n };\n\n const [results, total] = await Promise.all([\n historyQuery.findMany({\n where: whereClause,\n populate: ['createdBy'],\n orderBy: { createdAt: 'desc' },\n limit,\n offset: (pageNum - 1) * limit,\n }),\n historyQuery.count({ where: whereClause }),\n ]);\n\n const sanitizedResults = (results || []).map((ver: any) => ({\n ...ver,\n createdBy: ver.createdBy\n ? {\n id: ver.createdBy.id,\n firstname: ver.createdBy.firstname,\n lastname: ver.createdBy.lastname,\n username: ver.createdBy.username,\n email: ver.createdBy.email,\n }\n : undefined,\n meta: {\n unknownAttributes: { added: {}, removed: {} },\n },\n }));\n\n ctx.status = 200;\n ctx.body = {\n data: sanitizedResults,\n meta: {\n pagination: {\n page: pageNum,\n pageSize: limit,\n pageCount: Math.ceil(total / limit) || 1,\n total,\n },\n },\n };\n } else if (ctx.method === 'PUT' && ctx.path.endsWith('/restore')) {\n const match = ctx.path.match(/\\/content-manager\\/history-versions\\/([^/]+)\\/restore/);\n const versionId = match?.[1];\n if (!versionId) return;\n\n const historyQuery = strapi.db?.query?.('plugin::content-manager.history-version');\n const version = await historyQuery?.findOne?.({ where: { id: versionId } });\n if (!version) {\n ctx.status = 404;\n ctx.body = { error: 'Version not found' };\n return;\n }\n\n const restored = await strapi.documents(version.contentType).update({\n documentId: version.relatedDocumentId,\n locale: version.locale || undefined,\n data: version.data,\n });\n\n await recordContentHistoryVersion(strapi, {\n uid: version.contentType,\n documentId: version.relatedDocumentId,\n statusOverride: version.status || 'published',\n });\n\n ctx.status = 200;\n ctx.body = {\n data: {\n documentId: restored?.documentId || version.relatedDocumentId,\n },\n };\n }\n }\n });\n\n // Ensure database performance and concurrency resiliency for Content History\n try {\n const knex = strapi.db?.connection;\n if (knex) {\n // Optimize SQLite busy timeout to eliminate lock contention\n if (knex.client?.config?.client === 'sqlite3' || knex.client?.dialect === 'sqlite3') {\n knex.raw('PRAGMA busy_timeout = 10000;').catch(() => {});\n }\n\n // Ensure index exists on strapi_history_versions for high-speed queries\n knex.schema.hasTable('strapi_history_versions').then((hasTable: boolean) => {\n if (hasTable) {\n knex.raw(`\n CREATE INDEX IF NOT EXISTS idx_history_versions_lookup \n ON strapi_history_versions (content_type, related_document_id, created_at)\n `).catch(() => {});\n }\n }).catch(() => {});\n }\n } catch {}\n },\n routes,\n contentTypes,\n controllers: {\n bulkUpdater: bulkUpdaterController,\n audit: auditController,\n validationRules: validationRulesController,\n csv: csvController,\n },\n services: {\n bulkUpdater: bulkUpdaterService,\n audit: auditService,\n validationRules: validationRulesService,\n csv: csvService,\n contentHistory: contentHistoryService,\n },\n};\n"],"names":["csvService","buildDeepPopulate","currentVal","newValue","parsed","crypto","hasChange","auditService","record","diffs","revertedCount","rollbackDetails","index","targetField","validationRulesService","errors"],"mappings":"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"}
|