ScriptRunner.mjs 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. /* eslint-disable @overleaf/require-script-runner */
  2. // This *is* ScriptRunner.
  3. import { ScriptLog } from '../../app/src/models/ScriptLog.mjs'
  4. import Settings from '@overleaf/settings'
  5. const UNKNOWN = 'unknown'
  6. async function beforeScriptExecution(canonicalName, vars, scriptPath) {
  7. let log = new ScriptLog({
  8. canonicalName,
  9. filePathAtVersion: scriptPath,
  10. podName: process.env.OL_POD_NAME ?? UNKNOWN,
  11. username: process.env.OL_USERNAME ?? UNKNOWN,
  12. imageVersion: process.env.OL_IMAGE_VERSION ?? UNKNOWN,
  13. vars,
  14. })
  15. log = await log.save()
  16. // Print Script Log link if ran by a user
  17. if (process.env.OL_USERNAME) {
  18. console.log(
  19. '\n==================================' +
  20. '\n✨ Your script is running!' +
  21. '\n📊 Track progress at:' +
  22. `\n${Settings.adminUrl}/admin/script-log/${log._id}` +
  23. '\n==================================\n'
  24. )
  25. }
  26. return log._id
  27. }
  28. async function afterScriptExecution(logId, status) {
  29. await ScriptLog.findByIdAndUpdate(logId, { status, endTime: new Date() })
  30. }
  31. /**
  32. * @param {(trackProgress: (progress: string) => Promise<void>) => Promise<any>} main - Main function for the script
  33. * @param {Object} vars - Variables to be used in the script
  34. * @param {string} canonicalName - The canonical name of the script, default to filename
  35. * @param {string} scriptPath - The file path of the script, default to process.argv[1]
  36. * @returns {Promise<void>}
  37. * @async
  38. */
  39. export async function scriptRunner(
  40. main,
  41. vars = {},
  42. canonicalName = process.argv[1].split('/').pop().split('.')[0],
  43. scriptPath = process.argv[1]
  44. ) {
  45. const isSaaS = Boolean(Settings.overleaf)
  46. if (!isSaaS) {
  47. await main(async message => {
  48. console.warn(message)
  49. })
  50. return
  51. }
  52. const logId = await beforeScriptExecution(canonicalName, vars, scriptPath)
  53. async function trackProgress(message) {
  54. try {
  55. console.warn(message)
  56. await ScriptLog.findByIdAndUpdate(logId, {
  57. $push: {
  58. progressLogs: {
  59. timestamp: new Date(),
  60. message,
  61. },
  62. },
  63. })
  64. } catch (error) {
  65. console.error('Error tracking progress:', error)
  66. }
  67. }
  68. try {
  69. await main(trackProgress)
  70. } catch (error) {
  71. await afterScriptExecution(logId, 'error')
  72. throw error
  73. }
  74. await afterScriptExecution(logId, 'success')
  75. }