store.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. import Vue from 'vue'
  2. import Vuex from 'vuex'
  3. Vue.use(Vuex)
  4. <%
  5. const willResolveStoreModules = storeModules.some(s => s.src.indexOf('index.') !== 0)
  6. if (willResolveStoreModules) { %>
  7. const VUEX_PROPERTIES = ['state', 'getters', 'actions', 'mutations']
  8. <% } %>
  9. let store = {};
  10. (function updateModules () {
  11. <% storeModules.some(s => {
  12. if(s.src.indexOf('index.') === 0) { %>
  13. store = normalizeRoot(require('<%= relativeToBuild(srcDir, dir.store, s.src) %>'), '<%= dir.store %>/<%= s.src %>')
  14. <% return true }}) %>
  15. // If store is an exported method = classic mode (deprecated)
  16. <% if (isDev) { %>
  17. if (typeof store === 'function') {
  18. <%= isTest ? '// eslint-disable-next-line no-console' : '' %>
  19. return console.warn('Classic mode for store/ is deprecated and will be removed in Nuxt 3.')
  20. }<% } %>
  21. // Enforce store modules
  22. store.modules = store.modules || {}
  23. <% storeModules.forEach(s => {
  24. if(s.src.indexOf('index.') !== 0) { %>
  25. resolveStoreModules(require('<%= relativeToBuild(srcDir, dir.store, s.src) %>'), '<%= s.src %>')<% }}) %>
  26. // If the environment supports hot reloading...
  27. <% if (isDev) { %>
  28. if (process.client && module.hot) {
  29. // Whenever any Vuex module is updated...
  30. module.hot.accept([<% storeModules.forEach(s => { %>
  31. '<%= relativeToBuild(srcDir, dir.store, s.src) %>',<% }) %>
  32. ], () => {
  33. // Update `root.modules` with the latest definitions.
  34. updateModules()
  35. // Trigger a hot update in the store.
  36. window.<%= globals.nuxt %>.$store.hotUpdate(store)
  37. })
  38. }<% } %>
  39. })()
  40. // createStore
  41. export const createStore = store instanceof Function ? store : () => {
  42. return new Vuex.Store(Object.assign({
  43. strict: (process.env.NODE_ENV !== 'production')
  44. }, store))
  45. }
  46. function normalizeRoot (moduleData, filePath) {
  47. moduleData = moduleData.default || moduleData
  48. if (moduleData.commit) {
  49. throw new Error(`[nuxt] ${filePath} should export a method that returns a Vuex instance.`)
  50. }
  51. if (typeof moduleData !== 'function') {
  52. // Avoid TypeError: setting a property that has only a getter when overwriting top level keys
  53. moduleData = Object.assign({}, moduleData)
  54. }
  55. return normalizeModule(moduleData, filePath)
  56. }
  57. function normalizeModule (moduleData, filePath) {
  58. if (moduleData.state && typeof moduleData.state !== 'function') {
  59. <%= isTest ? '// eslint-disable-next-line no-console' : '' %>
  60. console.warn(`'state' should be a method that returns an object in ${filePath}`)
  61. const state = Object.assign({}, moduleData.state)
  62. // Avoid TypeError: setting a property that has only a getter when overwriting top level keys
  63. moduleData = Object.assign({}, moduleData, { state: () => state })
  64. }
  65. return moduleData
  66. }
  67. <% if (willResolveStoreModules) { %>
  68. function resolveStoreModules (moduleData, filename) {
  69. moduleData = moduleData.default || moduleData
  70. // Remove store src + extension (./foo/index.js -> foo/index)
  71. const namespace = filename.replace(/\.(<%= extensions %>)$/, '')
  72. const namespaces = namespace.split('/')
  73. let moduleName = namespaces[namespaces.length - 1]
  74. const filePath = `<%= dir.store %>/${filename}`
  75. moduleData = moduleName === 'state'
  76. ? normalizeState(moduleData, filePath)
  77. : normalizeModule(moduleData, filePath)
  78. // If src is a known Vuex property
  79. if (VUEX_PROPERTIES.includes(moduleName)) {
  80. const property = moduleName
  81. const propertyStoreModule = getStoreModule(store, namespaces, { isProperty: true })
  82. // Replace state since it's a function
  83. mergeProperty(propertyStoreModule, moduleData, property)
  84. return
  85. }
  86. // If file is foo/index.js, it should be saved as foo
  87. const isIndexModule = (moduleName === 'index')
  88. if (isIndexModule) {
  89. namespaces.pop()
  90. moduleName = namespaces[namespaces.length - 1]
  91. }
  92. const storeModule = getStoreModule(store, namespaces)
  93. for (const property of VUEX_PROPERTIES) {
  94. mergeProperty(storeModule, moduleData[property], property)
  95. }
  96. if (moduleData.namespaced === false) {
  97. delete storeModule.namespaced
  98. }
  99. }
  100. function normalizeState (moduleData, filePath) {
  101. if (typeof moduleData !== 'function') {
  102. <%= isTest ? '// eslint-disable-next-line no-console' : '' %>
  103. console.warn(`${filePath} should export a method that returns an object`)
  104. const state = Object.assign({}, moduleData)
  105. return () => state
  106. }
  107. return normalizeModule(moduleData, filePath)
  108. }
  109. function getStoreModule (storeModule, namespaces, { isProperty = false } = {}) {
  110. // If ./mutations.js
  111. if (!namespaces.length || (isProperty && namespaces.length === 1)) {
  112. return storeModule
  113. }
  114. const namespace = namespaces.shift()
  115. storeModule.modules[namespace] = storeModule.modules[namespace] || {}
  116. storeModule.modules[namespace].namespaced = true
  117. storeModule.modules[namespace].modules = storeModule.modules[namespace].modules || {}
  118. return getStoreModule(storeModule.modules[namespace], namespaces, { isProperty })
  119. }
  120. function mergeProperty (storeModule, moduleData, property) {
  121. if (!moduleData) {
  122. return
  123. }
  124. if (property === 'state') {
  125. storeModule.state = moduleData || storeModule.state
  126. } else {
  127. storeModule[property] = Object.assign({}, storeModule[property], moduleData)
  128. }
  129. }
  130. <% } %>