Gruntfile.coffee 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. fs = require "fs"
  2. module.exports = (grunt) ->
  3. grunt.loadNpmTasks 'grunt-contrib-coffee'
  4. grunt.loadNpmTasks 'grunt-contrib-less'
  5. grunt.loadNpmTasks 'grunt-contrib-clean'
  6. grunt.loadNpmTasks 'grunt-mocha-test'
  7. grunt.loadNpmTasks 'grunt-available-tasks'
  8. grunt.loadNpmTasks 'grunt-contrib-requirejs'
  9. grunt.loadNpmTasks 'grunt-execute'
  10. grunt.loadNpmTasks 'grunt-bunyan'
  11. grunt.loadNpmTasks 'grunt-sed'
  12. grunt.loadNpmTasks 'grunt-git-rev-parse'
  13. grunt.loadNpmTasks 'grunt-file-append'
  14. grunt.loadNpmTasks 'grunt-file-append'
  15. grunt.loadNpmTasks 'grunt-env'
  16. config =
  17. execute:
  18. app:
  19. src: "app.js"
  20. coffee:
  21. app_dir:
  22. expand: true,
  23. flatten: false,
  24. cwd: 'app/coffee',
  25. src: ['**/*.coffee'],
  26. dest: 'app/js/',
  27. ext: '.js'
  28. app:
  29. src: 'app.coffee'
  30. dest: 'app.js'
  31. sharejs:
  32. options:
  33. join: true
  34. files:
  35. "public/js/libs/sharejs.js": [
  36. "public/coffee/ide/editor/sharejs/header.coffee"
  37. "public/coffee/ide/editor/sharejs/vendor/types/helpers.coffee"
  38. "public/coffee/ide/editor/sharejs/vendor/types/text.coffee"
  39. "public/coffee/ide/editor/sharejs/vendor/types/text-api.coffee"
  40. "public/coffee/ide/editor/sharejs/vendor/client/microevent.coffee"
  41. "public/coffee/ide/editor/sharejs/vendor/client/doc.coffee"
  42. "public/coffee/ide/editor/sharejs/vendor/client/ace.coffee"
  43. ]
  44. client:
  45. expand: true,
  46. flatten: false,
  47. cwd: 'public/coffee',
  48. src: ['**/*.coffee'],
  49. dest: 'public/js/',
  50. ext: '.js'
  51. smoke_tests:
  52. expand: true,
  53. flatten: false,
  54. cwd: 'test/smoke/coffee',
  55. src: ['**/*.coffee'],
  56. dest: 'test/smoke/js/',
  57. ext: '.js'
  58. unit_tests:
  59. expand: true,
  60. flatten: false,
  61. cwd: 'test/UnitTests/coffee',
  62. src: ['**/*.coffee'],
  63. dest: 'test/UnitTests/js/',
  64. ext: '.js'
  65. acceptance_tests:
  66. expand: true,
  67. flatten: false,
  68. cwd: 'test/acceptance/coffee',
  69. src: ['**/*.coffee'],
  70. dest: 'test/acceptance/js/',
  71. ext: '.js'
  72. less:
  73. app:
  74. files:
  75. "public/stylesheets/style.css": "public/stylesheets/style.less"
  76. env:
  77. run:
  78. add:
  79. NODE_TLS_REJECT_UNAUTHORIZED:0
  80. requirejs:
  81. compile:
  82. options:
  83. optimize:"uglify2"
  84. uglify2:
  85. mangle: false
  86. appDir: "public/js"
  87. baseUrl: "./"
  88. dir: "public/minjs"
  89. inlineText: false
  90. preserveLicenseComments: false
  91. paths:
  92. "moment": "libs/moment-2.9.0"
  93. "mathjax": "/js/libs/mathjax/MathJax.js?config=TeX-AMS_HTML"
  94. "libs/pdf": "libs/pdfjs-1.3.91/pdf"
  95. shim:
  96. "libs/pdf":
  97. deps: ["libs/pdfjs-1.3.91/compatibility"]
  98. skipDirOptimize: true
  99. modules: [
  100. {
  101. name: "main",
  102. exclude: ["libs"]
  103. }, {
  104. name: "ide",
  105. exclude: ["libs", "libs/pdf"]
  106. }, {
  107. name: "libs"
  108. },{
  109. name: "ace/mode-latex"
  110. }
  111. ]
  112. clean:
  113. app: ["app/js"]
  114. unit_tests: ["test/UnitTests/js"]
  115. acceptance_tests: ["test/acceptance/js"]
  116. mochaTest:
  117. unit:
  118. src: ["test/UnitTests/js/#{grunt.option('feature') or '**'}/*.js"]
  119. options:
  120. reporter: grunt.option('reporter') or 'spec'
  121. grep: grunt.option("grep")
  122. smoke:
  123. src: ['test/smoke/js/**/*.js']
  124. options:
  125. reporter: grunt.option('reporter') or 'spec'
  126. grep: grunt.option("grep")
  127. acceptance:
  128. src: ["test/acceptance/js/#{grunt.option('feature') or '**'}/*.js"]
  129. options:
  130. timeout: 10000
  131. reporter: grunt.option('reporter') or 'spec'
  132. grep: grunt.option("grep")
  133. "git-rev-parse":
  134. version:
  135. options:
  136. prop: 'commit'
  137. file_append:
  138. default_options: files: [ {
  139. append: '\n//ide.js is complete - used for automated testing'
  140. input: 'public/minjs/ide.js'
  141. output: 'public/minjs/ide.js'
  142. }]
  143. sed:
  144. version:
  145. path: "app/views/sentry.jade"
  146. pattern: '@@COMMIT@@',
  147. replacement: '<%= commit %>',
  148. release:
  149. path: "app/views/sentry.jade"
  150. pattern: "@@RELEASE@@"
  151. replacement: process.env.BUILD_NUMBER || "(unknown build)"
  152. availabletasks:
  153. tasks:
  154. options:
  155. filter: 'exclude',
  156. tasks: [
  157. 'coffee'
  158. 'less'
  159. 'clean'
  160. 'mochaTest'
  161. 'availabletasks'
  162. 'wrap_sharejs'
  163. 'requirejs'
  164. 'execute'
  165. 'bunyan'
  166. ]
  167. groups:
  168. "Compile tasks": [
  169. "compile:server"
  170. "compile:client"
  171. "compile:tests"
  172. "compile"
  173. "compile:unit_tests"
  174. "compile:smoke_tests"
  175. "compile:css"
  176. "compile:minify"
  177. "install"
  178. ]
  179. "Test tasks": [
  180. "test:unit"
  181. "test:acceptance"
  182. ]
  183. "Run tasks": [
  184. "run"
  185. "default"
  186. ]
  187. "Misc": [
  188. "help"
  189. ]
  190. moduleCompileServerTasks = []
  191. moduleCompileUnitTestTasks = []
  192. moduleUnitTestTasks = []
  193. moduleCompileClientTasks = []
  194. moduleIdeClientSideIncludes = []
  195. moduleMainClientSideIncludes = []
  196. if fs.existsSync "./modules"
  197. for module in fs.readdirSync "./modules"
  198. if fs.existsSync "./modules/#{module}/index.coffee"
  199. config.coffee["module_#{module}_server"] = {
  200. expand: true,
  201. flatten: false,
  202. cwd: "modules/#{module}/app/coffee",
  203. src: ['**/*.coffee'],
  204. dest: "modules/#{module}/app/js",
  205. ext: '.js'
  206. }
  207. config.coffee["module_#{module}_index"] = {
  208. src: "modules/#{module}/index.coffee",
  209. dest: "modules/#{module}/index.js"
  210. }
  211. moduleCompileServerTasks.push "coffee:module_#{module}_server"
  212. moduleCompileServerTasks.push "coffee:module_#{module}_index"
  213. config.coffee["module_#{module}_unit_tests"] = {
  214. expand: true,
  215. flatten: false,
  216. cwd: "modules/#{module}/test/unit/coffee",
  217. src: ['**/*.coffee'],
  218. dest: "modules/#{module}/test/unit/js",
  219. ext: '.js'
  220. }
  221. config.mochaTest["module_#{module}_unit"] = {
  222. src: ["modules/#{module}/test/unit/js/*.js"]
  223. options:
  224. reporter: grunt.option('reporter') or 'spec'
  225. grep: grunt.option("grep")
  226. }
  227. moduleCompileUnitTestTasks.push "coffee:module_#{module}_unit_tests"
  228. moduleUnitTestTasks.push "mochaTest:module_#{module}_unit"
  229. if fs.existsSync "./modules/#{module}/public/coffee/ide/index.coffee"
  230. config.coffee["module_#{module}_client_ide"] = {
  231. expand: true,
  232. flatten: false,
  233. cwd: "modules/#{module}/public/coffee/ide",
  234. src: ['**/*.coffee'],
  235. dest: "public/js/ide/#{module}",
  236. ext: '.js'
  237. }
  238. moduleCompileClientTasks.push "coffee:module_#{module}_client_ide"
  239. moduleIdeClientSideIncludes.push "ide/#{module}/index"
  240. if fs.existsSync "./modules/#{module}/public/coffee/main/index.coffee"
  241. config.coffee["module_#{module}_client_main"] = {
  242. expand: true,
  243. flatten: false,
  244. cwd: "modules/#{module}/public/coffee/main",
  245. src: ['**/*.coffee'],
  246. dest: "public/js/main/#{module}",
  247. ext: '.js'
  248. }
  249. moduleCompileClientTasks.push "coffee:module_#{module}_client_main"
  250. moduleMainClientSideIncludes.push "main/#{module}/index"
  251. grunt.initConfig config
  252. grunt.registerTask 'wrap_sharejs', 'Wrap the compiled ShareJS code for AMD module loading', () ->
  253. content = fs.readFileSync "public/js/libs/sharejs.js"
  254. fs.writeFileSync "public/js/libs/sharejs.js", """
  255. define(["ace/ace"], function() {
  256. #{content}
  257. return window.sharejs;
  258. });
  259. """
  260. grunt.registerTask 'help', 'Display this help list', 'availabletasks'
  261. grunt.registerTask 'compile:modules:server', 'Compile all the modules', moduleCompileServerTasks
  262. grunt.registerTask 'compile:modules:unit_tests', 'Compile all the modules unit tests', moduleCompileUnitTestTasks
  263. grunt.registerTask 'compile:modules:client', 'Compile all the module client side code', moduleCompileClientTasks
  264. grunt.registerTask 'compile:modules:inject_clientside_includes', () ->
  265. content = fs.readFileSync("public/js/ide.js").toString()
  266. content = content.replace(/, "__IDE_CLIENTSIDE_INCLUDES__"/g, moduleIdeClientSideIncludes.map((i) -> ", \"#{i}\"").join(""))
  267. fs.writeFileSync "public/js/ide.js", content
  268. content = fs.readFileSync("public/js/main.js").toString()
  269. content = content.replace(/, "__MAIN_CLIENTSIDE_INCLUDES__"/g, moduleMainClientSideIncludes.map((i) -> ", \"#{i}\"").join(""))
  270. fs.writeFileSync "public/js/main.js", content
  271. grunt.registerTask 'compile:server', 'Compile the server side coffee script', ['clean:app', 'coffee:app', 'coffee:app_dir', 'compile:modules:server']
  272. grunt.registerTask 'compile:client', 'Compile the client side coffee script', ['coffee:client', 'coffee:sharejs', 'wrap_sharejs', "compile:modules:client", 'compile:modules:inject_clientside_includes']
  273. grunt.registerTask 'compile:css', 'Compile the less files to css', ['less']
  274. grunt.registerTask 'compile:minify', 'Concat and minify the client side js', ['requirejs', "file_append"]
  275. grunt.registerTask 'compile:unit_tests', 'Compile the unit tests', ['clean:unit_tests', 'coffee:unit_tests']
  276. grunt.registerTask 'compile:acceptance_tests', 'Compile the acceptance tests', ['clean:acceptance_tests', 'coffee:acceptance_tests']
  277. grunt.registerTask 'compile:smoke_tests', 'Compile the smoke tests', ['coffee:smoke_tests']
  278. grunt.registerTask 'compile:tests', 'Compile all the tests', ['compile:smoke_tests', 'compile:unit_tests']
  279. grunt.registerTask 'compile', 'Compiles everything need to run web-sharelatex', ['compile:server', 'compile:client', 'compile:css']
  280. grunt.registerTask 'install', "Compile everything when installing as an npm module", ['compile']
  281. grunt.registerTask 'test:unit', 'Run the unit tests (use --grep=<regex> or --feature=<feature> for individual tests)', ['compile:server', 'compile:modules:server', 'compile:unit_tests', 'compile:modules:unit_tests', 'mochaTest:unit'].concat(moduleUnitTestTasks)
  282. grunt.registerTask 'test:acceptance', 'Run the acceptance tests (use --grep=<regex> or --feature=<feature> for individual tests)', ['compile:acceptance_tests', 'mochaTest:acceptance']
  283. grunt.registerTask 'test:smoke', 'Run the smoke tests', ['compile:smoke_tests', 'mochaTest:smoke']
  284. grunt.registerTask 'test:modules:unit', 'Run the unit tests for the modules', ['compile:modules:server', 'compile:modules:unit_tests'].concat(moduleUnitTestTasks)
  285. grunt.registerTask 'run', "Compile and run the web-sharelatex server", ['compile', 'bunyan', 'env:run', 'execute']
  286. grunt.registerTask 'default', 'run'
  287. grunt.registerTask 'version', "Write the version number into sentry.jade", ['git-rev-parse', 'sed']
  288. grunt.registerTask 'create-admin-user', "Create a user with the given email address and make them an admin. Update in place if the user already exists", () ->
  289. done = @async()
  290. email = grunt.option("email")
  291. if !email?
  292. console.error "Usage: grunt create-admin-user --email joe@example.com"
  293. process.exit(1)
  294. settings = require "settings-sharelatex"
  295. UserRegistrationHandler = require "./app/js/Features/User/UserRegistrationHandler"
  296. OneTimeTokenHandler = require "./app/js/Features/Security/OneTimeTokenHandler"
  297. UserRegistrationHandler.registerNewUser {
  298. email: email
  299. password: require("crypto").randomBytes(32).toString("hex")
  300. }, (error, user) ->
  301. if error? and error?.message != "EmailAlreadyRegistered"
  302. throw error
  303. user.isAdmin = true
  304. user.save (error) ->
  305. throw error if error?
  306. ONE_WEEK = 7 * 24 * 60 * 60 # seconds
  307. OneTimeTokenHandler.getNewToken user._id, { expiresIn: ONE_WEEK }, (err, token)->
  308. return next(err) if err?
  309. console.log ""
  310. console.log """
  311. Successfully created #{email} as an admin user.
  312. Please visit the following URL to set a password for #{email} and log in:
  313. #{settings.siteUrl}/user/password/set?passwordResetToken=#{token}
  314. """
  315. done()