UNPKG

n8n-nodes-binalyze-air

Version:

Binalyze AIR nodes for automating DFIR with n8n workflows

960 lines (959 loc) 37.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaselinesOperations = void 0; exports.extractBaselineId = extractBaselineId; exports.isValidBaseline = isValidBaseline; exports.executeBaselines = executeBaselines; exports.getAssetsByOrganization = getAssetsByOrganization; exports.getTasksByAsset = getTasksByAsset; exports.getAssetsByOrganizationForReport = getAssetsByOrganizationForReport; exports.getComparisonTasksByAsset = getComparisonTasksByAsset; const n8n_workflow_1 = require("n8n-workflow"); const helpers_1 = require("../utils/helpers"); const baseline_1 = require("../api/baseline/baseline"); const organizations_1 = require("./organizations"); const assets_1 = require("./assets"); const assets_2 = require("../api/assets/assets"); const tasks_1 = require("./tasks"); exports.BaselinesOperations = [ { displayName: 'Operation', name: 'operation', type: 'options', noDataExpression: true, displayOptions: { show: { resource: ['baselines'], }, }, options: [ { name: 'Acquire Baseline', value: 'acquireBaseline', description: 'Acquire baseline for endpoints', action: 'Acquire a baseline', }, { name: 'Compare Baselines', value: 'compareBaseline', description: 'Compare two baseline acquisition results from the same endpoint', action: 'Compare baselines', }, { name: 'Get Comparison Report', value: 'getComparisonReport', description: 'Get baseline comparison report', action: 'Get comparison report', }, ], default: 'acquireBaseline', }, { displayName: 'Organization', name: 'organizationId', type: 'resourceLocator', default: { mode: 'id', value: '0' }, placeholder: 'Select organization...', displayOptions: { show: { resource: ['baselines'], operation: ['acquireBaseline'], }, }, modes: [ { displayName: 'From List', name: 'list', type: 'list', placeholder: 'Select an organization...', typeOptions: { searchListMethod: 'getOrganizations', searchable: true, }, }, { displayName: 'By ID', name: 'id', type: 'string', validation: [ { type: 'regex', properties: { regex: '^[0-9]+$', errorMessage: 'Organization ID must be a number', }, }, ], placeholder: 'Enter organization ID', }, ], required: true, description: 'The organization to use for baseline acquisition', }, { displayName: 'Case', name: 'caseId', type: 'resourceLocator', default: { mode: 'list', value: '' }, placeholder: 'Select a case...', displayOptions: { show: { resource: ['baselines'], operation: ['acquireBaseline'], }, }, modes: [ { displayName: 'From List', name: 'list', type: 'list', placeholder: 'Select a case...', typeOptions: { searchListMethod: 'getCases', searchable: true, }, }, { displayName: 'By ID', name: 'id', type: 'string', validation: [ { type: 'regex', properties: { regex: '^[a-zA-Z0-9-_]+$', errorMessage: 'Not a valid case ID (must contain only letters, numbers, hyphens, and underscores)', }, }, ], placeholder: 'Enter case ID', }, ], required: true, description: 'The case for baseline acquisition', }, { displayName: 'Task Name', name: 'taskName', type: 'string', default: '', placeholder: 'Enter task name', displayOptions: { show: { resource: ['baselines'], operation: ['compareBaseline'], }, }, description: 'Optional custom name for the comparison task (alphanumeric characters only)', }, { displayName: 'Organization', name: 'organizationIdForCompare', type: 'resourceLocator', default: { mode: 'list', value: '' }, placeholder: 'Select an organization...', displayOptions: { show: { resource: ['baselines'], operation: ['compareBaseline'], }, }, modes: [ { displayName: 'From List', name: 'list', type: 'list', placeholder: 'Select an organization...', typeOptions: { searchListMethod: 'getOrganizations', searchable: true, }, }, { displayName: 'By ID', name: 'id', type: 'string', validation: [ { type: 'regex', properties: { regex: '^[0-9]+$', errorMessage: 'Organization ID must be a number', }, }, ], placeholder: 'Enter organization ID', }, ], required: true, description: 'The organization that owns the asset', }, { displayName: 'Asset', name: 'assetIdForCompare', type: 'resourceLocator', default: { mode: 'list', value: '' }, placeholder: 'Select an asset...', displayOptions: { show: { resource: ['baselines'], operation: ['compareBaseline'], }, }, modes: [ { displayName: 'From List', name: 'list', type: 'list', placeholder: 'Select an asset...', typeOptions: { searchListMethod: 'getAssetsByOrganization', searchable: true, }, }, { displayName: 'By ID', name: 'id', type: 'string', validation: [ { type: 'regex', properties: { regex: '^[a-zA-Z0-9-_]+$', errorMessage: 'Not a valid asset ID (must contain only letters, numbers, hyphens, and underscores)', }, }, ], placeholder: 'Enter asset ID', }, ], required: true, description: 'The asset to compare baselines for', }, { displayName: 'Baseline 1', name: 'baseline1TaskId', type: 'resourceLocator', default: { mode: 'list', value: '' }, placeholder: 'Select first baseline task...', displayOptions: { show: { resource: ['baselines'], operation: ['compareBaseline'], }, }, modes: [ { displayName: 'From List', name: 'list', type: 'list', placeholder: 'Select a task...', typeOptions: { searchListMethod: 'getTasksByAsset', searchable: true, }, }, { displayName: 'By ID', name: 'id', type: 'string', validation: [ { type: 'regex', properties: { regex: '^[a-zA-Z0-9-_]+$', errorMessage: 'Not a valid task ID (must contain only letters, numbers, hyphens, and underscores)', }, }, ], placeholder: 'Enter task ID', }, ], required: true, description: 'The first baseline acquisition task to compare. Must be a completed baseline acquisition task from the selected asset.', }, { displayName: 'Baseline 2', name: 'baseline2TaskId', type: 'resourceLocator', default: { mode: 'list', value: '' }, placeholder: 'Select second baseline task...', displayOptions: { show: { resource: ['baselines'], operation: ['compareBaseline'], }, }, modes: [ { displayName: 'From List', name: 'list', type: 'list', placeholder: 'Select a task...', typeOptions: { searchListMethod: 'getTasksByAsset', searchable: true, }, }, { displayName: 'By ID', name: 'id', type: 'string', validation: [ { type: 'regex', properties: { regex: '^[a-zA-Z0-9-_]+$', errorMessage: 'Not a valid task ID (must contain only letters, numbers, hyphens, and underscores)', }, }, ], placeholder: 'Enter task ID', }, ], required: true, description: 'The second baseline acquisition task to compare. Must be a completed baseline acquisition task from the selected asset.', }, { displayName: 'Organization', name: 'organizationIdForReport', type: 'resourceLocator', default: { mode: 'list', value: '' }, placeholder: 'Select an organization...', displayOptions: { show: { resource: ['baselines'], operation: ['getComparisonReport'], }, }, modes: [ { displayName: 'From List', name: 'list', type: 'list', placeholder: 'Select an organization...', typeOptions: { searchListMethod: 'getOrganizations', searchable: true, }, }, { displayName: 'By ID', name: 'id', type: 'string', validation: [ { type: 'regex', properties: { regex: '^[0-9]+$', errorMessage: 'Organization ID must be a number', }, }, ], placeholder: 'Enter organization ID', }, ], required: true, description: 'The organization that owns the asset', }, { displayName: 'Asset', name: 'assetIdForReport', type: 'resourceLocator', default: { mode: 'list', value: '' }, placeholder: 'Select an asset...', displayOptions: { show: { resource: ['baselines'], operation: ['getComparisonReport'], }, }, modes: [ { displayName: 'From List', name: 'list', type: 'list', placeholder: 'Select an asset...', typeOptions: { searchListMethod: 'getAssetsByOrganizationForReport', searchable: true, }, }, { displayName: 'By ID', name: 'id', type: 'string', validation: [ { type: 'regex', properties: { regex: '^[a-zA-Z0-9-_]+$', errorMessage: 'Not a valid asset ID (must contain only letters, numbers, hyphens, and underscores)', }, }, ], placeholder: 'Enter asset ID', }, ], required: true, description: 'The asset to get comparison report for', }, { displayName: 'Comparison Task', name: 'comparisonTaskId', type: 'resourceLocator', default: { mode: 'list', value: '' }, placeholder: 'Select comparison task...', displayOptions: { show: { resource: ['baselines'], operation: ['getComparisonReport'], }, }, modes: [ { displayName: 'From List', name: 'list', type: 'list', placeholder: 'Select a comparison task...', typeOptions: { searchListMethod: 'getComparisonTasksByAsset', searchable: true, }, }, { displayName: 'By ID', name: 'id', type: 'string', validation: [ { type: 'regex', properties: { regex: '^[a-zA-Z0-9-_]+$', errorMessage: 'Not a valid task ID (must contain only letters, numbers, hyphens, and underscores)', }, }, ], placeholder: 'Enter task ID', }, ], required: true, description: 'The baseline comparison task to get the report for. Must be a completed baseline comparison task for the selected asset.', }, { displayName: 'Endpoint Filters (Required)', name: 'endpointFilters', type: 'collection', placeholder: 'Add Filter', default: {}, displayOptions: { show: { resource: ['baselines'], operation: ['acquireBaseline'], }, }, required: true, description: 'At least one filter must be defined to target specific endpoints', options: [ { displayName: 'Exclude Specific Endpoint IDs', name: 'excludedEndpointIds', type: 'string', default: '', placeholder: 'Enter comma-separated endpoint IDs', description: 'Exclude specific endpoint IDs (comma-separated)', }, { displayName: 'Filter By Endpoint Name', name: 'name', type: 'string', default: '', placeholder: 'Enter endpoint name', description: 'Filter endpoints by name', }, { displayName: 'Filter By Group Full Path', name: 'groupFullPath', type: 'string', default: '', placeholder: 'Enter group full path', description: 'Filter endpoints by group full path', }, { displayName: 'Filter By Group ID', name: 'groupId', type: 'string', default: '', placeholder: 'Enter group ID', description: 'Filter endpoints by group ID', }, { displayName: 'Filter By IP Address', name: 'ipAddress', type: 'string', default: '', placeholder: 'Enter IP address', description: 'Filter endpoints by IP address', }, { displayName: 'Filter By Isolation Status', name: 'isolationStatus', type: 'multiOptions', default: [], placeholder: 'Select isolation status', options: [ { name: 'Isolated', value: 'isolated', }, { name: 'Not Isolated', value: 'not_isolated', }, ], description: 'Filter endpoints by isolation status', }, { displayName: 'Filter By Issue', name: 'issue', type: 'string', default: '', placeholder: 'Enter issue', description: 'Filter endpoints by issue', }, { displayName: 'Filter By Management Status', name: 'managedStatus', type: 'multiOptions', default: [], placeholder: 'Select management status', options: [ { name: 'Managed', value: 'managed', }, { name: 'Unmanaged', value: 'unmanaged', }, ], description: 'Filter endpoints by management status', }, { displayName: 'Filter By Online Status', name: 'onlineStatus', type: 'multiOptions', default: [], placeholder: 'Select online status', options: [ { name: 'Online', value: 'online', }, { name: 'Offline', value: 'offline', }, ], description: 'Filter endpoints by online status', }, { displayName: 'Filter By Organization IDs', name: 'organizationIds', type: 'string', default: '', placeholder: 'Enter comma-separated organization IDs', description: 'Filter endpoints by organization IDs (comma-separated)', }, { displayName: 'Filter By Platform', name: 'platform', type: 'multiOptions', default: [], placeholder: 'Select platforms', options: [ { name: 'Windows', value: 'windows', }, { name: 'Linux', value: 'linux', }, { name: 'macOS', value: 'darwin', }, ], description: 'Filter endpoints by platform', }, { displayName: 'Filter By Policy', name: 'policy', type: 'string', default: '', placeholder: 'Enter policy', description: 'Filter endpoints by policy', }, { displayName: 'Filter By Search Term', name: 'searchTerm', type: 'string', default: '', placeholder: 'Enter search term', description: 'Filter endpoints by search term', }, { displayName: 'Filter By Tags', name: 'tags', type: 'string', default: '', placeholder: 'Enter comma-separated tags', description: 'Filter endpoints by tags (comma-separated)', }, { displayName: 'Filter By Version', name: 'version', type: 'string', default: '', placeholder: 'Enter version', description: 'Filter endpoints by version', }, { displayName: 'Include Specific Endpoint IDs', name: 'includedEndpointIds', type: 'string', default: '', placeholder: 'Enter comma-separated endpoint IDs', description: 'Include specific endpoint IDs (comma-separated)', }, ], }, ]; function extractBaselineId(baseline) { return (0, helpers_1.extractEntityId)(baseline, 'baseline'); } function isValidBaseline(baseline) { return (0, helpers_1.isValidEntity)(baseline, ['name']); } async function executeBaselines() { const items = this.getInputData(); const returnData = []; try { const credentials = await (0, helpers_1.getAirCredentials)(this); for (let i = 0; i < items.length; i++) { try { const operation = this.getNodeParameter('operation', i); let responseData; switch (operation) { case 'acquireBaseline': responseData = await executeAcquireBaseline.call(this, credentials, i); break; case 'compareBaseline': responseData = await executeCompareBaseline.call(this, credentials, i); break; case 'getComparisonReport': responseData = await executeGetComparisonReport.call(this, credentials, i); break; default: throw new Error(`The operation "${operation}" is not supported`); } returnData.push({ json: responseData, pairedItem: { item: i }, }); } catch (error) { (0, helpers_1.handleExecuteError)(this, error, i, returnData); } } return [returnData]; } catch (error) { const formattedError = (0, helpers_1.catchAndFormatError)(error, 'executeBaselines'); throw formattedError; } } async function executeAcquireBaseline(credentials, itemIndex) { const organizationId = this.getNodeParameter('organizationId', itemIndex); const caseId = this.getNodeParameter('caseId', itemIndex); const endpointFilters = this.getNodeParameter('endpointFilters', itemIndex, {}); const organizationIdValue = (0, helpers_1.normalizeAndValidateId)(organizationId.value || organizationId, 'Organization ID'); const caseIdValue = (0, helpers_1.normalizeAndValidateId)(caseId.value || caseId, 'Case ID'); const hasFilter = Boolean(endpointFilters.searchTerm || endpointFilters.name || endpointFilters.ipAddress || (endpointFilters.platform && endpointFilters.platform.length > 0) || (endpointFilters.onlineStatus && endpointFilters.onlineStatus.length > 0) || (endpointFilters.managedStatus && endpointFilters.managedStatus.length > 0) || endpointFilters.tags || endpointFilters.groupId || endpointFilters.groupFullPath || (endpointFilters.isolationStatus && endpointFilters.isolationStatus.length > 0) || endpointFilters.issue || endpointFilters.policy || endpointFilters.version || endpointFilters.organizationIds || endpointFilters.includedEndpointIds || endpointFilters.excludedEndpointIds || organizationIdValue !== '0'); if (!hasFilter) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'At least one endpoint filter must be provided for baseline acquisition', { itemIndex }); } const filter = {}; if (endpointFilters.searchTerm) filter.searchTerm = endpointFilters.searchTerm; if (endpointFilters.name) filter.name = endpointFilters.name; if (endpointFilters.ipAddress) filter.ipAddress = endpointFilters.ipAddress; if (endpointFilters.groupId) filter.groupId = endpointFilters.groupId; if (endpointFilters.groupFullPath) filter.groupFullPath = endpointFilters.groupFullPath; if (endpointFilters.managedStatus && endpointFilters.managedStatus.length > 0) { filter.managedStatus = endpointFilters.managedStatus; } if (endpointFilters.isolationStatus && endpointFilters.isolationStatus.length > 0) { filter.isolationStatus = endpointFilters.isolationStatus; } if (endpointFilters.platform && endpointFilters.platform.length > 0) { filter.platform = endpointFilters.platform; } if (endpointFilters.issue) filter.issue = endpointFilters.issue; if (endpointFilters.onlineStatus && endpointFilters.onlineStatus.length > 0) { filter.onlineStatus = endpointFilters.onlineStatus; } if (endpointFilters.tags) { filter.tags = endpointFilters.tags.split(',').map((tag) => tag.trim()); } if (endpointFilters.version) filter.version = endpointFilters.version; if (endpointFilters.policy) filter.policy = endpointFilters.policy; if (endpointFilters.includedEndpointIds) { filter.includedEndpointIds = endpointFilters.includedEndpointIds.split(',').map((id) => id.trim()); } if (endpointFilters.excludedEndpointIds) { filter.excludedEndpointIds = endpointFilters.excludedEndpointIds.split(',').map((id) => id.trim()); } filter.organizationIds = [Number(organizationIdValue)]; const request = { caseId: caseIdValue, filter, }; const response = await baseline_1.api.acquireBaseline(this, credentials, request); (0, helpers_1.validateApiResponse)(response, 'Acquire baseline'); return response; } async function executeCompareBaseline(credentials, itemIndex) { var _a, _b, _c; const organizationResource = this.getNodeParameter('organizationIdForCompare', itemIndex); const assetResource = this.getNodeParameter('assetIdForCompare', itemIndex); const baseline1Resource = this.getNodeParameter('baseline1TaskId', itemIndex); const baseline2Resource = this.getNodeParameter('baseline2TaskId', itemIndex); const taskName = this.getNodeParameter('taskName', itemIndex); if (taskName && !/^[a-zA-Z0-9]*$/.test(taskName)) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Task name must contain only letters and numbers', { itemIndex }); } if (organizationResource.mode === 'name') { try { await (0, organizations_1.findOrganizationByName)(this, credentials, organizationResource.value); } catch (error) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message, { itemIndex }); } } else if (organizationResource.mode !== 'list' && organizationResource.mode !== 'id') { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid organization selection mode', { itemIndex }); } const endpointId = (0, helpers_1.normalizeAndValidateId)(assetResource.value || assetResource, 'Asset ID'); const task1Id = (0, helpers_1.normalizeAndValidateId)(baseline1Resource.value || baseline1Resource, 'Baseline 1 Task ID'); const task2Id = (0, helpers_1.normalizeAndValidateId)(baseline2Resource.value || baseline2Resource, 'Baseline 2 Task ID'); if (task1Id === task2Id) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'The two baseline tasks must be different', { itemIndex }); } const request = { endpointId, taskIds: [task1Id, task2Id], }; if (taskName) { request.taskName = taskName; } try { const response = await baseline_1.api.compareBaseline(this, credentials, request); (0, helpers_1.validateApiResponse)(response, 'Compare baseline'); return response; } catch (error) { if (((_a = error.message) === null || _a === void 0 ? void 0 : _a.includes('No task assignment found by id')) || ((_b = error.message) === null || _b === void 0 ? void 0 : _b.includes('No task(s) found by provided id(s)'))) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `No baseline task assignments found for the specified endpoint. Please ensure: 1. Both tasks are baseline acquisition tasks (not regular acquisitions) 2. Both tasks were assigned to and completed on the selected endpoint (Asset ID: ${endpointId}) 3. The baseline acquisitions have finished processing 4. Task IDs: ${task1Id}, ${task2Id} Note: A baseline acquisition task may be assigned to multiple endpoints. You can only compare baselines that were both executed on the same endpoint.`, { itemIndex }); } if ((_c = error.message) === null || _c === void 0 ? void 0 : _c.includes('Status must be completed for baseline')) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `One or both baseline tasks have not completed yet. Please ensure both baseline acquisitions have finished processing before comparing them. Task IDs: ${task1Id}, ${task2Id}`, { itemIndex }); } throw error; } } async function executeGetComparisonReport(credentials, itemIndex) { const assetResource = this.getNodeParameter('assetIdForReport', itemIndex); const taskResource = this.getNodeParameter('comparisonTaskId', itemIndex); const endpointId = (0, helpers_1.normalizeAndValidateId)(assetResource.value || assetResource, 'Asset ID'); const taskId = (0, helpers_1.normalizeAndValidateId)(taskResource.value || taskResource, 'Task ID'); const response = await baseline_1.api.getComparisonReport(this, credentials, endpointId, taskId); return response; } async function getAssetsByOrganization(searchTerm) { try { const credentials = await (0, helpers_1.getAirCredentials)(this); let organizationId = '0'; try { const currentParams = this.getCurrentNodeParameters(); if (currentParams && currentParams.organizationIdForCompare) { const orgResource = currentParams.organizationIdForCompare; if (typeof orgResource === 'object') { if (orgResource.mode === 'id' || orgResource.mode === 'list') { organizationId = orgResource.value || '0'; } } else if (typeof orgResource === 'string') { organizationId = orgResource; } } } catch (error) { } const assets = await (0, assets_1.fetchAllAssets)(this, credentials, organizationId, searchTerm); return (0, helpers_1.createListSearchResults)(assets, assets_1.isValidAsset, (asset) => ({ name: `${asset.name} (${asset.ipAddress})`, value: (0, assets_1.extractAssetId)(asset), }), searchTerm); } catch (error) { throw (0, helpers_1.catchAndFormatError)(error, 'loading assets'); } } async function getTasksByAsset(searchTerm) { var _a; try { const credentials = await (0, helpers_1.getAirCredentials)(this); let assetId; try { const currentParams = this.getCurrentNodeParameters(); if (currentParams && currentParams.assetIdForCompare) { const assetResource = currentParams.assetIdForCompare; if (typeof assetResource === 'object') { if (assetResource.mode === 'id' || assetResource.mode === 'list') { assetId = assetResource.value; } } else if (typeof assetResource === 'string') { assetId = assetResource; } } } catch (error) { } if (!assetId) { return { results: [] }; } const response = await assets_2.api.getAssetTasks(this, credentials, assetId); const tasks = ((_a = response.result) === null || _a === void 0 ? void 0 : _a.entities) || []; let baselineTasks = tasks.filter((task) => task.type === 'baseline-acquisition'); let filteredTasks = baselineTasks; if (searchTerm) { const searchLower = searchTerm.toLowerCase(); filteredTasks = baselineTasks.filter((task) => (task.name && task.name.toLowerCase().includes(searchLower)) || (task._id && task._id.toLowerCase().includes(searchLower)) || (task.type && task.type.toLowerCase().includes(searchLower))); } return (0, helpers_1.createListSearchResults)(filteredTasks, tasks_1.isValidTask, (task) => ({ name: `${task.name || `Task ${task._id}`} (${task.type || 'Baseline Acquisition'})`, value: task.taskId || task._id, }), searchTerm); } catch (error) { throw (0, helpers_1.catchAndFormatError)(error, 'loading tasks'); } } async function getAssetsByOrganizationForReport(searchTerm) { try { const credentials = await (0, helpers_1.getAirCredentials)(this); let organizationId = '0'; try { const currentParams = this.getCurrentNodeParameters(); if (currentParams && currentParams.organizationIdForReport) { const orgResource = currentParams.organizationIdForReport; if (typeof orgResource === 'object') { if (orgResource.mode === 'id' || orgResource.mode === 'list') { organizationId = orgResource.value || '0'; } } else if (typeof orgResource === 'string') { organizationId = orgResource; } } } catch (error) { } const assets = await (0, assets_1.fetchAllAssets)(this, credentials, organizationId, searchTerm); return (0, helpers_1.createListSearchResults)(assets, assets_1.isValidAsset, (asset) => ({ name: `${asset.name} (${asset.ipAddress})`, value: (0, assets_1.extractAssetId)(asset), }), searchTerm); } catch (error) { throw (0, helpers_1.catchAndFormatError)(error, 'loading assets'); } } async function getComparisonTasksByAsset(searchTerm) { var _a; try { const credentials = await (0, helpers_1.getAirCredentials)(this); let assetId; try { const currentParams = this.getCurrentNodeParameters(); if (currentParams && currentParams.assetIdForReport) { const assetResource = currentParams.assetIdForReport; if (typeof assetResource === 'object') { if (assetResource.mode === 'id' || assetResource.mode === 'list') { assetId = assetResource.value; } } else if (typeof assetResource === 'string') { assetId = assetResource; } } } catch (error) { } if (!assetId) { return { results: [] }; } const response = await assets_2.api.getAssetTasks(this, credentials, assetId); const tasks = ((_a = response.result) === null || _a === void 0 ? void 0 : _a.entities) || []; let comparisonTasks = tasks.filter((task) => task.type === 'baseline-comparison'); let filteredTasks = comparisonTasks; if (searchTerm) { const searchLower = searchTerm.toLowerCase(); filteredTasks = comparisonTasks.filter((task) => (task.name && task.name.toLowerCase().includes(searchLower)) || (task._id && task._id.toLowerCase().includes(searchLower)) || (task.type && task.type.toLowerCase().includes(searchLower))); } return (0, helpers_1.createListSearchResults)(filteredTasks, tasks_1.isValidTask, (task) => ({ name: `${task.name || `Task ${task._id}`} (${task.type || 'Baseline Comparison'})`, value: task.taskId || task._id, }), searchTerm); } catch (error) { throw (0, helpers_1.catchAndFormatError)(error, 'loading comparison tasks'); } } //# sourceMappingURL=baselines.js.map