// Generate a "software footprint" detection rule from simple inputs, in the // shape the deployment model already uses (`detectionType` + `detectionRule`). // MSI maps to a product-code rule; file/registry produce Intune-style custom // PowerShell detection scripts so they flow straight through publishing without // extra mapping. Pure + unit-tested. function fileDetectionScript({ path, version }) { const lines = [`$path = '${path.replace(/'/g, "''")}'`, 'if (Test-Path -LiteralPath $path) {']; if (version) { lines.push(" $found = (Get-Item -LiteralPath $path).VersionInfo.ProductVersion"); lines.push(` if ($found -and [version]$found -ge [version]'${version}') { Write-Output 'Detected'; exit 0 }`); } else { lines.push(" Write-Output 'Detected'; exit 0"); } lines.push('}'); lines.push('exit 1'); return lines.join('\n'); } function registryDetectionScript({ keyPath, valueName, valueData }) { const key = keyPath.replace(/'/g, "''"); const lines = [`$key = '${key}'`]; if (valueName) { lines.push("$value = (Get-ItemProperty -LiteralPath $key -ErrorAction SilentlyContinue).'" + valueName.replace(/'/g, "''") + "'"); if (valueData) { lines.push(`if ($value -eq '${valueData.replace(/'/g, "''")}') { Write-Output 'Detected'; exit 0 }`); } else { lines.push("if ($null -ne $value) { Write-Output 'Detected'; exit 0 }"); } } else { lines.push("if (Test-Path -LiteralPath $key) { Write-Output 'Detected'; exit 0 }"); } lines.push('exit 1'); return lines.join('\n'); } export function buildDetectionRule(input = {}) { switch (input.type) { case 'msi': { if (!input.productCode) throw new Error('productCode is required for MSI detection'); return { detectionType: 'msi-product-code', detectionRule: input.productCode, description: `MSI product code ${input.productCode}` }; } case 'file': { if (!input.path) throw new Error('path is required for file detection'); return { detectionType: 'custom-script', detectionRule: fileDetectionScript(input), description: input.version ? `File ${input.path} version ≥ ${input.version}` : `File exists: ${input.path}` }; } case 'registry': { if (!input.keyPath) throw new Error('keyPath is required for registry detection'); return { detectionType: 'custom-script', detectionRule: registryDetectionScript(input), description: input.valueName ? `Registry ${input.keyPath}\\${input.valueName}` : `Registry key ${input.keyPath}` }; } default: throw new Error(`Unknown detection type "${input.type}" (expected msi, file, or registry)`); } }