UNPKG

@softchef/cdk-iot-device-management

Version:

IoT device management is composed of things, thing types, thing groups, jobs, files API services. The constructs can be used independently, that are based on full-managed service to create an API Gateway & Lambda function.

216 lines (215 loc) 8.46 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.constructStack = void 0; const constructStack = () => { let absoluteEntries = []; let relativeEntries = []; const entriesNameSet = new Set(); const sort = (entries) => entries.sort((a, b) => stepWeights[b.step] - stepWeights[a.step] || priorityWeights[b.priority || "normal"] - priorityWeights[a.priority || "normal"]); const removeByName = (toRemove) => { let isRemoved = false; const filterCb = (entry) => { if (entry.name && entry.name === toRemove) { isRemoved = true; entriesNameSet.delete(toRemove); return false; } return true; }; absoluteEntries = absoluteEntries.filter(filterCb); relativeEntries = relativeEntries.filter(filterCb); return isRemoved; }; const removeByReference = (toRemove) => { let isRemoved = false; const filterCb = (entry) => { if (entry.middleware === toRemove) { isRemoved = true; if (entry.name) entriesNameSet.delete(entry.name); return false; } return true; }; absoluteEntries = absoluteEntries.filter(filterCb); relativeEntries = relativeEntries.filter(filterCb); return isRemoved; }; const cloneTo = (toStack) => { absoluteEntries.forEach((entry) => { toStack.add(entry.middleware, { ...entry }); }); relativeEntries.forEach((entry) => { toStack.addRelativeTo(entry.middleware, { ...entry }); }); return toStack; }; const expandRelativeMiddlewareList = (from) => { const expandedMiddlewareList = []; from.before.forEach((entry) => { if (entry.before.length === 0 && entry.after.length === 0) { expandedMiddlewareList.push(entry); } else { expandedMiddlewareList.push(...expandRelativeMiddlewareList(entry)); } }); expandedMiddlewareList.push(from); from.after.reverse().forEach((entry) => { if (entry.before.length === 0 && entry.after.length === 0) { expandedMiddlewareList.push(entry); } else { expandedMiddlewareList.push(...expandRelativeMiddlewareList(entry)); } }); return expandedMiddlewareList; }; const getMiddlewareList = () => { const normalizedAbsoluteEntries = []; const normalizedRelativeEntries = []; const normalizedEntriesNameMap = {}; absoluteEntries.forEach((entry) => { const normalizedEntry = { ...entry, before: [], after: [], }; if (normalizedEntry.name) normalizedEntriesNameMap[normalizedEntry.name] = normalizedEntry; normalizedAbsoluteEntries.push(normalizedEntry); }); relativeEntries.forEach((entry) => { const normalizedEntry = { ...entry, before: [], after: [], }; if (normalizedEntry.name) normalizedEntriesNameMap[normalizedEntry.name] = normalizedEntry; normalizedRelativeEntries.push(normalizedEntry); }); normalizedRelativeEntries.forEach((entry) => { if (entry.toMiddleware) { const toMiddleware = normalizedEntriesNameMap[entry.toMiddleware]; if (toMiddleware === undefined) { throw new Error(`${entry.toMiddleware} is not found when adding ${entry.name || "anonymous"} middleware ${entry.relation} ${entry.toMiddleware}`); } if (entry.relation === "after") { toMiddleware.after.push(entry); } if (entry.relation === "before") { toMiddleware.before.push(entry); } } }); const mainChain = sort(normalizedAbsoluteEntries) .map(expandRelativeMiddlewareList) .reduce((wholeList, expendedMiddlewareList) => { wholeList.push(...expendedMiddlewareList); return wholeList; }, []); return mainChain.map((entry) => entry.middleware); }; const stack = { add: (middleware, options = {}) => { const { name, override } = options; const entry = { step: "initialize", priority: "normal", middleware, ...options, }; if (name) { if (entriesNameSet.has(name)) { if (!override) throw new Error(`Duplicate middleware name '${name}'`); const toOverrideIndex = absoluteEntries.findIndex((entry) => entry.name === name); const toOverride = absoluteEntries[toOverrideIndex]; if (toOverride.step !== entry.step || toOverride.priority !== entry.priority) { throw new Error(`"${name}" middleware with ${toOverride.priority} priority in ${toOverride.step} step cannot be ` + `overridden by same-name middleware with ${entry.priority} priority in ${entry.step} step.`); } absoluteEntries.splice(toOverrideIndex, 1); } entriesNameSet.add(name); } absoluteEntries.push(entry); }, addRelativeTo: (middleware, options) => { const { name, override } = options; const entry = { middleware, ...options, }; if (name) { if (entriesNameSet.has(name)) { if (!override) throw new Error(`Duplicate middleware name '${name}'`); const toOverrideIndex = relativeEntries.findIndex((entry) => entry.name === name); const toOverride = relativeEntries[toOverrideIndex]; if (toOverride.toMiddleware !== entry.toMiddleware || toOverride.relation !== entry.relation) { throw new Error(`"${name}" middleware ${toOverride.relation} "${toOverride.toMiddleware}" middleware cannot be overridden ` + `by same-name middleware ${entry.relation} "${entry.toMiddleware}" middleware.`); } relativeEntries.splice(toOverrideIndex, 1); } entriesNameSet.add(name); } relativeEntries.push(entry); }, clone: () => cloneTo(exports.constructStack()), use: (plugin) => { plugin.applyToStack(stack); }, remove: (toRemove) => { if (typeof toRemove === "string") return removeByName(toRemove); else return removeByReference(toRemove); }, removeByTag: (toRemove) => { let isRemoved = false; const filterCb = (entry) => { const { tags, name } = entry; if (tags && tags.includes(toRemove)) { if (name) entriesNameSet.delete(name); isRemoved = true; return false; } return true; }; absoluteEntries = absoluteEntries.filter(filterCb); relativeEntries = relativeEntries.filter(filterCb); return isRemoved; }, concat: (from) => { const cloned = cloneTo(exports.constructStack()); cloned.use(from); return cloned; }, applyToStack: cloneTo, resolve: (handler, context) => { for (const middleware of getMiddlewareList().reverse()) { handler = middleware(handler, context); } return handler; }, }; return stack; }; exports.constructStack = constructStack; const stepWeights = { initialize: 5, serialize: 4, build: 3, finalizeRequest: 2, deserialize: 1, }; const priorityWeights = { high: 3, normal: 2, low: 1, };