widgets.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. module.exports = api => {
  2. const { registerWidget, onAction, setSharedData } = api.namespace('org.vue.widgets.')
  3. if (process.env.VUE_APP_CLI_UI_DEV) {
  4. api.addClientAddon({
  5. id: 'org.vue.widgets.client-addon.dev',
  6. url: 'http://localhost:8097/index.js'
  7. })
  8. } else {
  9. api.addClientAddon({
  10. id: 'org.vue.widgets.client-addon',
  11. path: '@vue/cli-ui-addon-widgets/dist'
  12. })
  13. }
  14. // Welcome widget
  15. registerWidget({
  16. id: 'welcome',
  17. title: 'org.vue.widgets.welcome.title',
  18. description: 'org.vue.widgets.welcome.description',
  19. icon: 'mood',
  20. component: 'org.vue.widgets.components.welcome',
  21. minWidth: 3,
  22. minHeight: 4,
  23. maxWidth: 3,
  24. maxHeight: 4,
  25. maxCount: 1
  26. })
  27. // Kill port widget
  28. registerWidget({
  29. id: 'kill-port',
  30. title: 'org.vue.widgets.kill-port.title',
  31. description: 'org.vue.widgets.kill-port.description',
  32. icon: 'flash_on',
  33. component: 'org.vue.widgets.components.kill-port',
  34. minWidth: 2,
  35. minHeight: 1,
  36. maxWidth: 2,
  37. maxHeight: 1,
  38. maxCount: 1
  39. })
  40. setSharedData('kill-port.status', 'idle')
  41. onAction('actions.kill-port', async params => {
  42. const fkill = require('fkill')
  43. setSharedData('kill-port.status', 'killing')
  44. try {
  45. await fkill(`:${params.port}`)
  46. setSharedData('kill-port.status', 'killed')
  47. } catch (e) {
  48. console.log(e)
  49. setSharedData('kill-port.status', 'error')
  50. }
  51. })
  52. // Plugin updates
  53. setSharedData('plugin-updates.status', {
  54. status: 'ok',
  55. lastUpdate: Date.now()
  56. })
  57. registerWidget({
  58. id: 'plugin-updates',
  59. title: 'org.vue.widgets.plugin-updates.title',
  60. description: 'org.vue.widgets.plugin-updates.description',
  61. icon: 'extension',
  62. component: 'org.vue.widgets.components.plugin-updates',
  63. minWidth: 2,
  64. minHeight: 1,
  65. maxWidth: 2,
  66. maxHeight: 1,
  67. maxCount: 1
  68. })
  69. // Dependency updates
  70. setSharedData('dependency-updates.status', {
  71. status: 'loading',
  72. lastUpdate: null
  73. })
  74. registerWidget({
  75. id: 'dependency-updates',
  76. title: 'org.vue.widgets.dependency-updates.title',
  77. description: 'org.vue.widgets.dependency-updates.description',
  78. icon: 'collections_bookmark',
  79. component: 'org.vue.widgets.components.dependency-updates',
  80. minWidth: 2,
  81. minHeight: 1,
  82. maxWidth: 2,
  83. maxHeight: 1,
  84. maxCount: 1
  85. })
  86. // Vulnerability check
  87. let lastAudit = null
  88. setSharedData('vulnerability.status', {
  89. status: 'loading',
  90. lastUpdate: lastAudit,
  91. count: 0,
  92. message: null
  93. })
  94. setSharedData('vulnerability.details', {
  95. vulnerabilities: [],
  96. summary: {}
  97. })
  98. registerWidget({
  99. id: 'vulnerability',
  100. title: 'org.vue.widgets.vulnerability.title',
  101. description: 'org.vue.widgets.vulnerability.description',
  102. icon: 'verified_user',
  103. component: 'org.vue.widgets.components.vulnerability',
  104. detailsComponent: 'org.vue.widgets.components.vulnerability-details',
  105. minWidth: 2,
  106. minHeight: 1,
  107. maxWidth: 2,
  108. maxHeight: 1,
  109. maxCount: 1
  110. })
  111. async function checkVulnerability (params) {
  112. setSharedData('vulnerability.status', {
  113. status: 'loading',
  114. lastUpdate: lastAudit,
  115. count: 0,
  116. message: null
  117. })
  118. const { auditProject } = require('./utils/audit')
  119. const { status, details } = await auditProject(api.getCwd())
  120. status.lastUpdate = lastAudit = Date.now()
  121. setSharedData('vulnerability.status', status)
  122. setSharedData('vulnerability.details', details)
  123. }
  124. onAction('actions.check-vunerability', checkVulnerability)
  125. checkVulnerability()
  126. // Run task
  127. registerWidget({
  128. id: 'run-task',
  129. title: 'org.vue.widgets.run-task.title',
  130. description: 'org.vue.widgets.run-task.description',
  131. icon: 'assignment',
  132. component: 'org.vue.widgets.components.run-task',
  133. minWidth: 2,
  134. minHeight: 1,
  135. maxWidth: 2,
  136. maxHeight: 1,
  137. needsUserConfig: true,
  138. onConfigOpen: async ({ context }) => {
  139. const tasks = require('@vue/cli-ui/apollo-server/connectors/tasks')
  140. return {
  141. prompts: [
  142. {
  143. name: 'task',
  144. type: 'list',
  145. message: 'org.vue.widgets.run-task.prompts.task',
  146. choices: (await tasks.list(undefined, context)).map(task => ({
  147. name: task.name,
  148. value: task.id
  149. }))
  150. }
  151. ]
  152. }
  153. }
  154. })
  155. // News
  156. registerWidget({
  157. id: 'news',
  158. title: 'org.vue.widgets.news.title',
  159. description: 'org.vue.widgets.news.description',
  160. icon: 'rss_feed',
  161. component: 'org.vue.widgets.components.news',
  162. detailsComponent: 'org.vue.widgets.components.news',
  163. minWidth: 2,
  164. minHeight: 1,
  165. maxWidth: 6,
  166. maxHeight: 6,
  167. defaultWidth: 2,
  168. defaultHeight: 3,
  169. openDetailsButton: true,
  170. defaultConfig: () => ({
  171. url: 'https://vuenews.fireside.fm/rss'
  172. }),
  173. onConfigOpen: async ({ context }) => {
  174. return {
  175. prompts: [
  176. {
  177. name: 'url',
  178. type: 'input',
  179. message: 'org.vue.widgets.news.prompts.url',
  180. validate: input => !!input
  181. }
  182. ]
  183. }
  184. }
  185. })
  186. const newsCache = global['org.vue.newsCache'] = global['org.vue.newsCache'] || {}
  187. let parser
  188. onAction('actions.fetch-news', async params => {
  189. if (!parser) {
  190. const Parser = require('rss-parser')
  191. parser = new Parser()
  192. }
  193. if (!params.force) {
  194. const cached = newsCache[params.url]
  195. if (cached) return cached
  196. }
  197. let url = params.url
  198. // GitHub repo
  199. if (url.match(/^[\w_.-]+\/[\w_.-]+$/)) {
  200. url = `https://github.com/${url}/releases.atom`
  201. }
  202. const result = await parser.parseURL(url)
  203. newsCache[params.url] = result
  204. return result
  205. })
  206. }