{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { Pipeline, PipelineResult } from 'open-guardrail-core';\n\nexport class GuardrailBlockedError extends Error {\n  readonly stage: 'input' | 'output';\n  readonly result: PipelineResult;\n\n  constructor(stage: 'input' | 'output', result: PipelineResult) {\n    super(`Guardrail blocked at ${stage} stage: ${result.action}`);\n    this.name = 'GuardrailBlockedError';\n    this.stage = stage;\n    this.result = result;\n  }\n}\n\nexport type InputExtractor = (req: any) => string;\n\nexport interface GuardrailMiddlewareOptions {\n  input?: Pipeline;\n  output?: Pipeline;\n  inputFrom?: 'body' | 'query' | InputExtractor;\n  fieldName?: string;\n  onBlocked?: (result: PipelineResult, req: any, res: any) => void;\n}\n\nexport interface OutputGuardOptions {\n  output: Pipeline;\n  onBlocked?: (result: PipelineResult) => void;\n}\n\nfunction extractText(req: any, options: GuardrailMiddlewareOptions): string | null {\n  const field = options.fieldName ?? 'message';\n  const source = options.inputFrom ?? 'body';\n\n  if (typeof source === 'function') {\n    return source(req) ?? null;\n  }\n\n  const container = source === 'query' ? req.query : req.body;\n  if (!container) return null;\n\n  const value = container[field];\n  return typeof value === 'string' ? value : null;\n}\n\n/**\n * Create an Express middleware that guards incoming request text.\n *\n * @example\n * ```typescript\n * import express from 'express';\n * import { pipe, promptInjection } from 'open-guardrail';\n * import { createGuardrailMiddleware } from 'open-guardrail-express';\n *\n * const app = express();\n * app.use(express.json());\n * app.use(createGuardrailMiddleware({\n *   input: pipe(promptInjection({ action: 'block' })),\n * }));\n * ```\n */\nexport function createGuardrailMiddleware(options: GuardrailMiddlewareOptions) {\n  return async (req: any, res: any, next: any) => {\n    try {\n      if (options.input) {\n        const text = extractText(req, options);\n\n        if (text) {\n          const result = await options.input.run(text);\n          req.guardrailResult = result;\n\n          if (!result.passed) {\n            if (options.onBlocked) {\n              options.onBlocked(result, req, res);\n              return;\n            }\n\n            const guardName = result.results.find((r) => !r.passed)?.guardName ?? 'unknown';\n            res.status(403).json({\n              error: 'blocked',\n              action: result.action,\n              guardName,\n            });\n            return;\n          }\n\n          if (result.output && result.output !== text) {\n            const field = options.fieldName ?? 'message';\n            const source = options.inputFrom ?? 'body';\n            if (source === 'body' || source === undefined) {\n              req.body[field] = result.output;\n            }\n          }\n        }\n      }\n\n      next();\n    } catch (err) {\n      next(err);\n    }\n  };\n}\n\n/**\n * Guard output text before sending a response.\n *\n * @example\n * ```typescript\n * import { pipe, pii } from 'open-guardrail';\n * import { createOutputGuard } from 'open-guardrail-express';\n *\n * const guardOutput = createOutputGuard({\n *   output: pipe(pii({ entities: ['email'], action: 'mask' })),\n * });\n *\n * app.post('/chat', async (req, res) => {\n *   const llmResponse = await getLLMResponse(req.body.message);\n *   const safe = await guardOutput(llmResponse);\n *   res.json({ reply: safe });\n * });\n * ```\n */\nexport function createOutputGuard(options: OutputGuardOptions) {\n  return async (text: string): Promise<string> => {\n    const result = await options.output.run(text);\n\n    if (!result.passed) {\n      options.onBlocked?.(result);\n      throw new GuardrailBlockedError('output', result);\n    }\n\n    return result.output ?? text;\n  };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEO,IAAM,wBAAN,cAAoC,MAAM;AAAA,EACtC;AAAA,EACA;AAAA,EAET,YAAY,OAA2B,QAAwB;AAC7D,UAAM,wBAAwB,KAAK,WAAW,OAAO,MAAM,EAAE;AAC7D,SAAK,OAAO;AACZ,SAAK,QAAQ;AACb,SAAK,SAAS;AAAA,EAChB;AACF;AAiBA,SAAS,YAAY,KAAU,SAAoD;AACjF,QAAM,QAAQ,QAAQ,aAAa;AACnC,QAAM,SAAS,QAAQ,aAAa;AAEpC,MAAI,OAAO,WAAW,YAAY;AAChC,WAAO,OAAO,GAAG,KAAK;AAAA,EACxB;AAEA,QAAM,YAAY,WAAW,UAAU,IAAI,QAAQ,IAAI;AACvD,MAAI,CAAC,UAAW,QAAO;AAEvB,QAAM,QAAQ,UAAU,KAAK;AAC7B,SAAO,OAAO,UAAU,WAAW,QAAQ;AAC7C;AAkBO,SAAS,0BAA0B,SAAqC;AAC7E,SAAO,OAAO,KAAU,KAAU,SAAc;AAC9C,QAAI;AACF,UAAI,QAAQ,OAAO;AACjB,cAAM,OAAO,YAAY,KAAK,OAAO;AAErC,YAAI,MAAM;AACR,gBAAM,SAAS,MAAM,QAAQ,MAAM,IAAI,IAAI;AAC3C,cAAI,kBAAkB;AAEtB,cAAI,CAAC,OAAO,QAAQ;AAClB,gBAAI,QAAQ,WAAW;AACrB,sBAAQ,UAAU,QAAQ,KAAK,GAAG;AAClC;AAAA,YACF;AAEA,kBAAM,YAAY,OAAO,QAAQ,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,aAAa;AACtE,gBAAI,OAAO,GAAG,EAAE,KAAK;AAAA,cACnB,OAAO;AAAA,cACP,QAAQ,OAAO;AAAA,cACf;AAAA,YACF,CAAC;AACD;AAAA,UACF;AAEA,cAAI,OAAO,UAAU,OAAO,WAAW,MAAM;AAC3C,kBAAM,QAAQ,QAAQ,aAAa;AACnC,kBAAM,SAAS,QAAQ,aAAa;AACpC,gBAAI,WAAW,UAAU,WAAW,QAAW;AAC7C,kBAAI,KAAK,KAAK,IAAI,OAAO;AAAA,YAC3B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,WAAK;AAAA,IACP,SAAS,KAAK;AACZ,WAAK,GAAG;AAAA,IACV;AAAA,EACF;AACF;AAqBO,SAAS,kBAAkB,SAA6B;AAC7D,SAAO,OAAO,SAAkC;AAC9C,UAAM,SAAS,MAAM,QAAQ,OAAO,IAAI,IAAI;AAE5C,QAAI,CAAC,OAAO,QAAQ;AAClB,cAAQ,YAAY,MAAM;AAC1B,YAAM,IAAI,sBAAsB,UAAU,MAAM;AAAA,IAClD;AAEA,WAAO,OAAO,UAAU;AAAA,EAC1B;AACF;","names":[]}