rerunArguments.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import { needsArgumentForm } from './needsArgumentForm.js'
  2. import { actionRequiresJustification } from './justificationTemplate.js'
  3. const nonStorableArgumentTypes = new Set([
  4. 'password',
  5. 'very_dangerous_raw_string'
  6. ])
  7. function isNonStorableArgumentType (type) {
  8. return nonStorableArgumentTypes.has(type)
  9. }
  10. function argumentSkipsValidation (type) {
  11. return type === 'confirmation' || type === 'html'
  12. }
  13. /**
  14. * Mirrors backend restartArgumentRequired: an argument needs a stored value
  15. * when it is validated and has no default. Proto ActionArgument has no
  16. * `required` field — only `defaultValue`.
  17. */
  18. function rerunArgumentRequired (arg) {
  19. if (argumentSkipsValidation(arg?.type)) {
  20. return false
  21. }
  22. const defaultValue = arg?.defaultValue ?? ''
  23. return defaultValue === ''
  24. }
  25. export function logEntryArgumentsToStartActionArgs (logEntry) {
  26. return (logEntry?.arguments ?? []).map((arg) => ({
  27. name: arg.name,
  28. value: arg.value
  29. }))
  30. }
  31. export function rerunNeedsArgumentForm (action, logEntry) {
  32. // Always re-prompt when justification is required so each execution is
  33. // explicitly justified rather than silently reusing a prior reason.
  34. if (actionRequiresJustification(action?.justification)) {
  35. return true
  36. }
  37. if (!needsArgumentForm(action)) {
  38. return false
  39. }
  40. return hasMissingRerunArguments(action, logEntry?.arguments ?? [])
  41. }
  42. export function hasMissingRerunArguments (action, storedArgs) {
  43. const stored = new Map(storedArgs.map((arg) => [arg.name, arg.value]))
  44. for (const arg of action?.arguments ?? []) {
  45. if (isNonStorableArgumentType(arg.type)) {
  46. return true
  47. }
  48. if (rerunArgumentRequired(arg) && !stored.has(arg.name)) {
  49. return true
  50. }
  51. }
  52. return false
  53. }
  54. /**
  55. * Builds history.state.prefilledArguments for ArgumentForm (not URL query),
  56. * matching ActionButton's prefill pattern and keeping values out of the URL.
  57. */
  58. export function buildRerunPrefilledArguments (logEntry) {
  59. const prefilled = {}
  60. for (const arg of logEntry?.arguments ?? []) {
  61. prefilled[arg.name] = arg.value
  62. }
  63. return prefilled
  64. }
  65. export function buildRerunStartActionArgs (bindingId, logEntry) {
  66. return {
  67. bindingId,
  68. arguments: logEntryArgumentsToStartActionArgs(logEntry)
  69. }
  70. }