Skip to content

Instantly share code, notes, and snippets.

@Restuta
Last active January 15, 2019 03:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Restuta/20e6352a37b59c69b0f260593fcb780b to your computer and use it in GitHub Desktop.
Save Restuta/20e6352a37b59c69b0f260593fcb780b to your computer and use it in GitHub Desktop.
With Audit Log prototype
// original version with binding to module instance
const { createAuditLogRecords } = require('../commands');
const getStepFactory = require('./get-factory-by-type');
const { createStep, updateStep } = require('./commands');
const applyStepUpdates = require('./apply-step-updates');
const createContainer = (items = []) => ({
getAll: () => items,
add: x => items.push(x),
});
// executes given function and then creates audit log records collected
const saveAuditLogAfterExecution = ({
createAuditLogRecordsCommand,
getAuditLogRecords,
}) => updateFunc => async (...args) => {
const results = await updateFunc(...args);
await createAuditLogRecordsCommand(getAuditLogRecords());
return results;
};
const withAuditLogCollector = ({ auditLogProducingFunction, collectAuditLogRecord }) => (
...args
) => {
const { updates, auditLogRecord } = auditLogProducingFunction(...args);
collectAuditLogRecord(auditLogRecord);
return updates;
};
const stepFactory = ({ stepType, uponTransactionCommit, transaction }) => {
const createStepCommand = createStep(transaction);
const updateStepCommand = updateStep(transaction);
const auditLogRecordsContainer = createContainer();
const applyUpdatesWithAuditLog = withAuditLogCollector({
auditLogProducingFunction: applyStepUpdates,
collectAuditLogRecord: auditLogRecordsContainer.add,
});
const { updateAsUser, updateAsAdmin } = getStepFactory(stepType)({
createStepCommand,
updateStepWithAuditLogCommand,
uponTransactionCommit,
createAuditLogRecords
});
const saveAuditLog = saveAuditLogAfterExecution({
createAuditLogRecordsCommand: createAuditLogRecords(transaction),
getAuditLogRecords: auditLogRecordsContainer.getAll,
});
return {
updateAsUser: saveAuditLog(updateAsUser),
updateAsAdmin: saveAuditLog(updateAsAdmin),
};
};
// ----------------
const { updateAsUser, updateAsAdmin } = withAuditLog(applyStepUpdates)(
(applyUpdatesWithAuditLog, getCollectedAuditLogRecords) => {
const { updateAsUser, updateAsAdmin } = getStepFactory(stepType)({
createStepCommand,
updateStepCommand,
applyUpdatesWithAuditLog,
uponTransactionCommit,
})
const createAuditLogRecordsCommand = createAuditLogRecords(transaction)
const executeWithAuditLog = updateFunc => async (...args) => {
const results = await updateFunc(...args);
await createAuditLogRecordsCommand(getCollectedAuditLogRecords());
return results;
};
const withAuditLog = executeWithAuditLog({
createAuditLogRecordsCommand: createAuditLogRecords(transaction),
getAuditLogRecords: auditLogRecordsContainer.getAll,
});
}
///
const { createAuditLogRecords } = require('../commands');
const getStepFactory = require('./get-factory-by-type');
const { createStep, updateStep } = require('./commands');
const applyStepUpdates = require('./apply-step-updates');
const createContainer = (items = []) => ({
getAll: () => items,
add: x => items.push(x),
});
// executes given function and then creates audit log records collected
const executeWithAuditLog = ({
createAuditLogRecordsCommand,
getAuditLogRecords,
}) => updateFunc => async (...args) => {
const results = await updateFunc(...args);
await createAuditLogRecordsCommand(getAuditLogRecords());
return results;
};
const withAuditLogCollector = ({ auditLogProducingFunction, collectAuditLogRecord }) => (
...args
) => {
const { updates, auditLogRecord } = auditLogProducingFunction(...args);
collectAuditLogRecord(auditLogRecord);
return updates;
};
const stepFactory = ({ stepType, uponTransactionCommit, transaction }) => {
const createStepCommand = createStep(transaction);
const updateStepCommand = updateStep(transaction);
const auditLogRecordsContainer = createContainer();
const applyUpdatesWithAuditLog = withAuditLogCollector({
auditLogProducingFunction: applyStepUpdates,
collectAuditLogRecord: auditLogRecordsContainer.add,
});
const { updateAsUser, updateAsAdmin } = getStepFactory(stepType)({
createStepCommand,
updateStepCommand,
applyUpdatesWithAuditLog,
uponTransactionCommit,
});
const withAuditLog = executeWithAuditLog({
createAuditLogRecordsCommand: createAuditLogRecords(transaction),
getAuditLogRecords: auditLogRecordsContainer.getAll,
});
return {
updateAsUser: withAuditLog(updateAsUser()),
updateAsAdmin: withAuditLog(updateAsAdmin),
};
};
module.exports = {
stepFactory,
};
// -----------
const updateFunc = ({ updateWithAuditLog }) => {};
const createAuditLogCollector = (
auditLogProducingFunction,
auditLogContainer = createContainer(),
) => ({
func: (...args) => {
{
const { updates, auditLogRecord } = auditLogProducingFunction(...args);
auditLogContainer.add(auditLogRecord);
return updates;
}
},
getCollectedAuditRecords: auditLogContainer.getAll,
addRecord: auditLogContainer.add,
});
const withAuditLog = updateFunc => auditLog => ({
func: updateFunc(auditLog.func),
getCollectedAuditRecords: auditLog.getCollectedAuditRecords,
addRecord: auditLog.add,
}
const saveAuditLogAfterExecution = createAuditLogRecordsCommand =>
({ getCollectedAuditRecords, func }) =>
async (...args) => {
const results = await func(...args);
await createAuditLogRecordsCommand(auditLog.getCollectedAuditRecords());
return results;
};
const auditLogCollector = (createAuditLogRecordsCommand, auditLogProducingFunction) =>
updateFunc => R.pipe(
createAuditLogCollector,
withAuditLog(updateFunc),
saveAuditLogAfterExecution(createAuditLogRecordsCommand)
)(auditLogProducingFunction)
// auditLog.foo() => updates (+ internal collect)
// auditLog.getCollectedItems()
function foo() {
const withAuditLog = auditLogCollector(createAuditLogRecordsCommand, auditLogProducingFunction);
return {
updateAsUser: withAuditLog(updateAsUser),
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment