@rancher/shell 0.3.3 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. package/assets/styles/app.scss +1 -1
  2. package/assets/styles/fonts/_fontstack.scss +11 -11
  3. package/assets/styles/vendor/vue-js-modal.scss +3 -3
  4. package/assets/translations/en-us.yaml +92 -22
  5. package/assets/translations/zh-hans.yaml +84 -15
  6. package/babel.config.js +13 -0
  7. package/chart/gatekeeper.vue +77 -0
  8. package/chart/istio.vue +108 -111
  9. package/chart/logging/index.vue +13 -4
  10. package/chart/monitoring/index.vue +15 -5
  11. package/chart/monitoring/steps/uninstall-v1.vue +2 -2
  12. package/chart/rancher-backup/index.vue +10 -3
  13. package/cloud-credential/aws.vue +1 -1
  14. package/cloud-credential/digitalocean.vue +1 -1
  15. package/cloud-credential/gcp.vue +1 -1
  16. package/cloud-credential/generic.vue +2 -2
  17. package/cloud-credential/linode.vue +1 -1
  18. package/cloud-credential/pnap.vue +1 -1
  19. package/components/ActionMenu.vue +3 -4
  20. package/components/AssignTo.vue +1 -1
  21. package/components/AsyncButton.vue +1 -1
  22. package/components/BannerGraphic.vue +1 -1
  23. package/components/ButtonDropdown.vue +2 -3
  24. package/components/ChartPsp.vue +76 -0
  25. package/components/CruResource.vue +6 -2
  26. package/components/DashboardMetrics.vue +12 -10
  27. package/components/DetailText.vue +1 -1
  28. package/components/DisableAuthProviderModal.vue +1 -1
  29. package/components/EmberPage.vue +1 -1
  30. package/components/EtcdInfoBanner.vue +5 -4
  31. package/components/ExplorerMembers.vue +1 -1
  32. package/components/ExplorerProjectsNamespaces.vue +15 -2
  33. package/components/FileDiff.vue +6 -7
  34. package/components/GrafanaDashboard.vue +18 -21
  35. package/components/LazyImage.vue +10 -12
  36. package/components/LogItem.vue +1 -1
  37. package/components/Markdown.vue +1 -1
  38. package/components/PromptRemove.vue +2 -2
  39. package/components/PromptRestore.vue +1 -1
  40. package/components/ResourceDetail/Masthead.vue +16 -0
  41. package/components/ResourceDetail/index.vue +21 -4
  42. package/components/ResourceList/index.vue +1 -1
  43. package/components/ResourceTable.vue +4 -1
  44. package/components/SingleClusterInfo.vue +2 -2
  45. package/components/SortableTable/THead.vue +1 -1
  46. package/components/SortableTable/index.vue +5 -2
  47. package/components/__tests__/AsyncButton.test.ts +3 -1
  48. package/components/__tests__/ChartPsp.test.ts +75 -0
  49. package/components/__tests__/CruResource.test.ts +3 -1
  50. package/components/auth/Principal.vue +1 -1
  51. package/components/fleet/FleetBundles.vue +3 -1
  52. package/components/fleet/FleetClusters.vue +1 -2
  53. package/components/fleet/FleetIntro.vue +9 -1
  54. package/components/fleet/FleetNoWorkspaces.vue +62 -0
  55. package/components/fleet/FleetSummary.vue +7 -1
  56. package/components/form/LabeledSelect.vue +14 -11
  57. package/components/form/MatchExpressions.vue +17 -2
  58. package/components/form/NameNsDescription.vue +31 -45
  59. package/components/form/ResourceSelector.vue +1 -1
  60. package/components/form/SecretSelector.vue +5 -1
  61. package/components/form/ServiceNameSelect.vue +1 -1
  62. package/components/form/SimpleSecretSelector.vue +9 -9
  63. package/components/form/__tests__/LabeledSelect.test.ts +138 -0
  64. package/components/form/__tests__/NameNsDescription.ts +32 -0
  65. package/components/formatter/InternalExternalIP.vue +6 -0
  66. package/components/formatter/InvolvedObjectLink.vue +54 -0
  67. package/components/formatter/Link.vue +20 -4
  68. package/components/formatter/LinkName.vue +6 -1
  69. package/components/formatter/ServiceTargets.vue +1 -1
  70. package/components/nav/Group.vue +2 -2
  71. package/components/nav/NamespaceFilter.vue +15 -11
  72. package/components/nav/TopLevelMenu.vue +2 -4
  73. package/components/nav/Type.vue +1 -1
  74. package/components/nav/WorkspaceSwitcher.vue +46 -5
  75. package/config/labels-annotations.js +17 -0
  76. package/config/product/auth.js +3 -2
  77. package/config/product/explorer.js +11 -4
  78. package/config/product/fleet.js +2 -0
  79. package/config/router.js +414 -0
  80. package/config/table-headers.js +10 -2
  81. package/config/types.js +11 -8
  82. package/config/uiplugins.js +30 -0
  83. package/content/docs/en-us/whats-new.md +10 -0
  84. package/content/docs/zh-hans/whats-new.md +11 -1
  85. package/core/plugin-helpers.js +64 -61
  86. package/core/plugin-routes.ts +23 -0
  87. package/creators/app/app.package.json +2 -1
  88. package/creators/app/files/.eslintrc.js +1 -1
  89. package/creators/app/files/babel.config.js +1 -18
  90. package/creators/app/files/vue.config.js +7 -0
  91. package/creators/app/init +5 -5
  92. package/creators/pkg/files/.github/workflows/build-extension.yml +111 -0
  93. package/creators/pkg/init +35 -4
  94. package/creators/update/init +1 -1
  95. package/detail/constraints.gatekeeper.sh.constraint.vue +20 -10
  96. package/detail/fleet.cattle.io.gitrepo.vue +19 -11
  97. package/detail/harvesterhci.io.management.cluster.vue +3 -3
  98. package/detail/provisioning.cattle.io.cluster.vue +54 -12
  99. package/detail/workload/index.vue +3 -3
  100. package/dialog/AddClusterMemberDialog.vue +1 -1
  101. package/dialog/AddProjectMemberDialog.vue +2 -2
  102. package/dialog/AddonConfigConfirmationDialog.vue +27 -15
  103. package/dialog/DiagnosticTimingsDialog.vue +1 -1
  104. package/dialog/ForceMachineRemoveDialog.vue +1 -1
  105. package/dialog/GenericPrompt.vue +18 -6
  106. package/dialog/RotateEncryptionKeyDialog.vue +1 -1
  107. package/dialog/SaveAsRKETemplateDialog.vue +1 -1
  108. package/dialog/ScaleMachineDownDialog.vue +1 -1
  109. package/edit/auth/github.vue +8 -8
  110. package/edit/auth/googleoauth.vue +5 -5
  111. package/edit/auth/ldap/index.vue +1 -1
  112. package/edit/auth/oidc.vue +1 -1
  113. package/edit/auth/saml.vue +1 -1
  114. package/edit/cis.cattle.io.clusterscan.vue +1 -1
  115. package/edit/fleet.cattle.io.clustergroup.vue +6 -4
  116. package/edit/fleet.cattle.io.gitrepo.vue +16 -3
  117. package/edit/helm.cattle.io.projecthelmchart.vue +5 -1
  118. package/edit/management.cattle.io.fleetworkspace.vue +141 -6
  119. package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +4 -1
  120. package/edit/management.cattle.io.setting.vue +1 -1
  121. package/edit/monitoring.coreos.com.alertmanagerconfig/types/webhook.vue +2 -2
  122. package/edit/monitoring.coreos.com.receiver/tls.vue +18 -18
  123. package/edit/monitoring.coreos.com.receiver/types/webhook.banner.vue +4 -4
  124. package/edit/monitoring.coreos.com.receiver/types/webhook.vue +1 -1
  125. package/edit/namespace.vue +2 -2
  126. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +126 -45
  127. package/edit/networking.k8s.io.networkpolicy/index.vue +1 -1
  128. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +10 -0
  129. package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +1 -0
  130. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +202 -2
  131. package/edit/provisioning.cattle.io.cluster/rke2.vue +248 -84
  132. package/edit/resources.cattle.io.backup.vue +1 -1
  133. package/edit/service.vue +1 -1
  134. package/edit/storage.k8s.io.storageclass/provisioners/driver.harvesterhci.io.vue +2 -2
  135. package/edit/workload/__tests__/Job.test.ts +3 -1
  136. package/edit/workload/index.vue +8 -3
  137. package/edit/workload/mixins/workload.js +16 -0
  138. package/layouts/default.vue +7 -3
  139. package/list/fleet.cattle.io.bundle.vue +6 -3
  140. package/list/fleet.cattle.io.clusterregistrationtoken.vue +3 -1
  141. package/list/fleet.cattle.io.gitrepo.vue +44 -5
  142. package/list/management.cattle.io.fleetworkspace.vue +45 -0
  143. package/list/node.vue +69 -16
  144. package/list/provisioning.cattle.io.cluster.vue +30 -1
  145. package/machine-config/azure.vue +97 -38
  146. package/middleware/authenticated.js +34 -0
  147. package/mixins/chart.js +73 -2
  148. package/mixins/resource-fetch.js +2 -2
  149. package/models/apps.statefulset.js +28 -0
  150. package/models/cluster/node.js +23 -2
  151. package/models/cluster.x-k8s.io.machine.js +4 -2
  152. package/models/clusterroletemplatebinding.js +7 -0
  153. package/models/constraints.gatekeeper.sh.constraint.js +9 -0
  154. package/models/fleet.cattle.io.cluster.js +19 -10
  155. package/models/fleet.cattle.io.gitrepo.js +7 -2
  156. package/models/management.cattle.io.cluster.js +1 -1
  157. package/models/management.cattle.io.fleetworkspace.js +12 -0
  158. package/models/management.cattle.io.gitreporestriction.js +5 -0
  159. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.js +3 -0
  160. package/models/namespace.js +5 -5
  161. package/models/provisioning.cattle.io.cluster.js +7 -5
  162. package/nuxt/App.js +210 -0
  163. package/nuxt/axios.js +186 -0
  164. package/nuxt/client.js +817 -0
  165. package/nuxt/components/nuxt-build-indicator.vue +143 -0
  166. package/nuxt/components/nuxt-child.js +122 -0
  167. package/nuxt/components/nuxt-error.vue +98 -0
  168. package/nuxt/components/nuxt-link.client.js +98 -0
  169. package/nuxt/components/nuxt-link.server.js +16 -0
  170. package/nuxt/components/nuxt-loading.vue +154 -0
  171. package/nuxt/components/nuxt.js +101 -0
  172. package/nuxt/cookie-universal-nuxt.js +9 -0
  173. package/nuxt/empty.js +1 -0
  174. package/nuxt/index.js +365 -0
  175. package/nuxt/jsonp.js +82 -0
  176. package/nuxt/loading.html +39 -0
  177. package/nuxt/middleware.js +12 -0
  178. package/nuxt/mixins/fetch.client.js +90 -0
  179. package/nuxt/mixins/fetch.server.js +69 -0
  180. package/nuxt/portal-vue.js +4 -0
  181. package/nuxt/server.js +312 -0
  182. package/nuxt/store.js +178 -0
  183. package/nuxt/utils.js +630 -0
  184. package/nuxt/views/app.template.html +9 -0
  185. package/nuxt/views/error.html +23 -0
  186. package/package.json +5 -9
  187. package/pages/auth/setup.vue +2 -2
  188. package/pages/c/_cluster/apps/charts/__tests__/install.helper.test.ts +33 -0
  189. package/pages/c/_cluster/apps/charts/chart.vue +4 -4
  190. package/pages/c/_cluster/apps/charts/install.helpers.js +26 -0
  191. package/pages/c/_cluster/apps/charts/install.vue +40 -66
  192. package/pages/c/_cluster/explorer/EventsTable.vue +5 -19
  193. package/pages/c/_cluster/explorer/index.vue +29 -25
  194. package/pages/c/_cluster/explorer/tools/index.vue +8 -8
  195. package/pages/c/_cluster/fleet/index.vue +95 -34
  196. package/pages/c/_cluster/gatekeeper/index.vue +1 -1
  197. package/pages/c/_cluster/istio/index.vue +5 -5
  198. package/pages/c/_cluster/manager/cloudCredential/index.vue +1 -1
  199. package/pages/c/_cluster/monitoring/index.vue +7 -0
  200. package/pages/c/_cluster/uiplugins/InstallDialog.vue +8 -8
  201. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +20 -7
  202. package/pages/c/_cluster/uiplugins/index.vue +49 -17
  203. package/pages/home.vue +9 -4
  204. package/pages/index.vue +10 -1
  205. package/plugins/clean-html-directive.js +31 -0
  206. package/plugins/dashboard-store/actions.js +32 -9
  207. package/plugins/dashboard-store/mutations.js +5 -2
  208. package/plugins/dashboard-store/resource-class.js +8 -1
  209. package/plugins/steve/mutations.js +3 -2
  210. package/plugins/steve/steve-description-class.js +5 -1
  211. package/plugins/steve/subscribe.js +63 -54
  212. package/plugins/steve-create-worker.js +14 -0
  213. package/promptRemove/management.cattle.io.globalrole.vue +2 -2
  214. package/promptRemove/management.cattle.io.project.vue +2 -2
  215. package/promptRemove/management.cattle.io.roletemplate.vue +2 -2
  216. package/promptRemove/pod.vue +1 -1
  217. package/public/index.html +65 -0
  218. package/rancher-components/components/Banner/Banner.test.ts +9 -1
  219. package/rancher-components/components/Banner/Banner.vue +1 -1
  220. package/rancher-components/components/Form/Checkbox/Checkbox.vue +2 -0
  221. package/rancher-components/components/Form/Radio/RadioButton.vue +1 -1
  222. package/scripts/build-pkg.sh +1 -0
  223. package/scripts/clean +6 -0
  224. package/scripts/extension/bundle +58 -0
  225. package/scripts/extension/helmpatch +89 -0
  226. package/scripts/extension/publish +314 -0
  227. package/scripts/test-plugins-build.sh +4 -0
  228. package/store/__tests__/index.test.ts +110 -0
  229. package/store/index.js +145 -58
  230. package/store/type-map.js +26 -19
  231. package/tsconfig.default.json +36 -0
  232. package/tsconfig.json +24 -0
  233. package/types/shell/index.d.ts +420 -343
  234. package/utils/__tests__/string.test.ts +12 -0
  235. package/utils/auth.js +65 -0
  236. package/utils/monitoring.js +2 -1
  237. package/utils/position.js +5 -8
  238. package/utils/router.scrollBehavior.js +80 -0
  239. package/utils/select.js +1 -3
  240. package/utils/socket.js +1 -0
  241. package/utils/string.js +13 -0
  242. package/utils/time.js +9 -0
  243. package/vue.config.js +679 -0
  244. package/yarn-error.log +196 -0
  245. package/chart/rancher-alerting-drivers.vue +0 -53
  246. package/chart/rancher-gatekeeper.vue +0 -37
  247. package/creators/app/files/nuxt.config.js +0 -6
  248. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.ts +0 -4
  249. package/nuxt.config.js +0 -798
package/nuxt/client.js ADDED
@@ -0,0 +1,817 @@
1
+ import Vue from 'vue'
2
+ import fetch from 'unfetch'
3
+ import middleware from './middleware.js'
4
+ import {
5
+ applyAsyncData,
6
+ promisify,
7
+ middlewareSeries,
8
+ sanitizeComponent,
9
+ resolveRouteComponents,
10
+ getMatchedComponents,
11
+ getMatchedComponentsInstances,
12
+ flatMapComponents,
13
+ setContext,
14
+ getLocation,
15
+ compile,
16
+ getQueryDiff,
17
+ globalHandleError,
18
+ isSamePath,
19
+ urlJoin
20
+ } from './utils.js'
21
+ import { createApp, NuxtError } from './index.js'
22
+ import fetchMixin from './mixins/fetch.client'
23
+ import NuxtLink from './components/nuxt-link.client.js' // should be included after ./index.js
24
+
25
+ // Fetch mixin
26
+ if (!Vue.__nuxt__fetch__mixin__) {
27
+ Vue.mixin(fetchMixin)
28
+ Vue.__nuxt__fetch__mixin__ = true
29
+ }
30
+
31
+ // Component: <NuxtLink>
32
+ Vue.component(NuxtLink.name, NuxtLink)
33
+ Vue.component('NLink', NuxtLink)
34
+
35
+ if (!global.fetch) { global.fetch = fetch }
36
+
37
+ // Global shared references
38
+ let _lastPaths = []
39
+ let app
40
+ let router
41
+ let store
42
+
43
+ // Try to rehydrate SSR data from window
44
+ const NUXT = window.__NUXT__ || {}
45
+
46
+ const $config = nuxt.publicRuntimeConfig || {}
47
+ if ($config._app) {
48
+ __webpack_public_path__ = urlJoin($config._app.cdnURL, $config._app.assetsPath)
49
+ }
50
+
51
+ Object.assign(Vue.config, {"silent":false,"performance":true})
52
+
53
+ const logs = NUXT.logs || []
54
+ if (logs.length > 0) {
55
+ const ssrLogStyle = 'background: #2E495E;border-radius: 0.5em;color: white;font-weight: bold;padding: 2px 0.5em;'
56
+ console.group && console.group ('%cNuxt SSR', ssrLogStyle)
57
+ logs.forEach(logObj => (console[logObj.type] || console.log)(...logObj.args))
58
+ delete NUXT.logs
59
+ console.groupEnd && console.groupEnd()
60
+ }
61
+
62
+ // Setup global Vue error handler
63
+ if (!Vue.config.$nuxt) {
64
+ const defaultErrorHandler = Vue.config.errorHandler
65
+ Vue.config.errorHandler = async (err, vm, info, ...rest) => {
66
+ // Call other handler if exist
67
+ let handled = null
68
+ if (typeof defaultErrorHandler === 'function') {
69
+ handled = defaultErrorHandler(err, vm, info, ...rest)
70
+ }
71
+ if (handled === true) {
72
+ return handled
73
+ }
74
+
75
+ if (vm && vm.$root) {
76
+ const nuxtApp = Object.keys(Vue.config.$nuxt)
77
+ .find(nuxtInstance => vm.$root[nuxtInstance])
78
+
79
+ // Show Nuxt Error Page
80
+ if (nuxtApp && vm.$root[nuxtApp].error && info !== 'render function') {
81
+ const currentApp = vm.$root[nuxtApp]
82
+
83
+ // Load error layout
84
+ let layout = (NuxtError.options || NuxtError).layout
85
+ if (typeof layout === 'function') {
86
+ layout = layout(currentApp.context)
87
+ }
88
+ if (layout) {
89
+ await currentApp.loadLayout(layout).catch(() => {})
90
+ }
91
+ currentApp.setLayout(layout)
92
+
93
+ currentApp.error(err)
94
+ }
95
+ }
96
+
97
+ if (typeof defaultErrorHandler === 'function') {
98
+ return handled
99
+ }
100
+
101
+ // Log to console
102
+ if (process.env.NODE_ENV !== 'production') {
103
+ console.error(err)
104
+ } else {
105
+ console.error(err.message || err)
106
+ }
107
+ }
108
+ Vue.config.$nuxt = {}
109
+ }
110
+ Vue.config.$nuxt.$nuxt = true
111
+
112
+ const errorHandler = Vue.config.errorHandler || console.error
113
+
114
+ // Create and mount App
115
+ createApp(null, nuxt.publicRuntimeConfig).then(mountApp).catch(errorHandler)
116
+
117
+ function componentOption (component, key, ...args) {
118
+ if (!component || !component.options || !component.options[key]) {
119
+ return {}
120
+ }
121
+ const option = component.options[key]
122
+ if (typeof option === 'function') {
123
+ return option(...args)
124
+ }
125
+ return option
126
+ }
127
+
128
+ function mapTransitions (toComponents, to, from) {
129
+ const componentTransitions = (component) => {
130
+ const transition = componentOption(component, 'transition', to, from) || {}
131
+ return (typeof transition === 'string' ? { name: transition } : transition)
132
+ }
133
+
134
+ const fromComponents = from ? getMatchedComponents(from) : []
135
+ const maxDepth = Math.max(toComponents.length, fromComponents.length)
136
+
137
+ const mergedTransitions = []
138
+ for (let i=0; i<maxDepth; i++) {
139
+ // Clone original objects to prevent overrides
140
+ const toTransitions = Object.assign({}, componentTransitions(toComponents[i]))
141
+ const transitions = Object.assign({}, componentTransitions(fromComponents[i]))
142
+
143
+ // Combine transitions & prefer `leave` properties of "from" route
144
+ Object.keys(toTransitions)
145
+ .filter(key => typeof toTransitions[key] !== 'undefined' && !key.toLowerCase().includes('leave'))
146
+ .forEach((key) => { transitions[key] = toTransitions[key] })
147
+
148
+ mergedTransitions.push(transitions)
149
+ }
150
+ return mergedTransitions
151
+ }
152
+
153
+ async function loadAsyncComponents (to, from, next) {
154
+ // Check if route changed (this._routeChanged), only if the page is not an error (for validate())
155
+ this._routeChanged = Boolean(app.nuxt.err) || from.name !== to.name
156
+ this._paramChanged = !this._routeChanged && from.path !== to.path
157
+ this._queryChanged = !this._paramChanged && from.fullPath !== to.fullPath
158
+ this._diffQuery = (this._queryChanged ? getQueryDiff(to.query, from.query) : [])
159
+
160
+ if ((this._routeChanged || this._paramChanged) && this.$loading.start && !this.$loading.manual) {
161
+ this.$loading.start()
162
+ }
163
+
164
+ try {
165
+ if (this._queryChanged) {
166
+ const Components = await resolveRouteComponents(
167
+ to,
168
+ (Component, instance) => ({ Component, instance })
169
+ )
170
+ // Add a marker on each component that it needs to refresh or not
171
+ const startLoader = Components.some(({ Component, instance }) => {
172
+ const watchQuery = Component.options.watchQuery
173
+ if (watchQuery === true) {
174
+ return true
175
+ }
176
+ if (Array.isArray(watchQuery)) {
177
+ return watchQuery.some(key => this._diffQuery[key])
178
+ }
179
+ if (typeof watchQuery === 'function') {
180
+ return watchQuery.apply(instance, [to.query, from.query])
181
+ }
182
+ return false
183
+ })
184
+
185
+ if (startLoader && this.$loading.start && !this.$loading.manual) {
186
+ this.$loading.start()
187
+ }
188
+ }
189
+ // Call next()
190
+ next()
191
+ } catch (error) {
192
+ const err = error || {}
193
+ const statusCode = err.statusCode || err.status || (err.response && err.response.status) || 500
194
+ const message = err.message || ''
195
+
196
+ // Handle chunk loading errors
197
+ // This may be due to a new deployment or a network problem
198
+ if (/^Loading( CSS)? chunk (\d)+ failed\./.test(message)) {
199
+ window.location.reload(true /* skip cache */)
200
+ return // prevent error page blinking for user
201
+ }
202
+
203
+ this.error({ statusCode, message })
204
+ this.$nuxt.$emit('routeChanged', to, from, err)
205
+ next()
206
+ }
207
+ }
208
+
209
+ function applySSRData (Component, ssrData) {
210
+ if (NUXT.serverRendered && ssrData) {
211
+ applyAsyncData(Component, ssrData)
212
+ }
213
+
214
+ Component._Ctor = Component
215
+ return Component
216
+ }
217
+
218
+ // Get matched components
219
+ function resolveComponents (route) {
220
+ return flatMapComponents(route, async (Component, _, match, key, index) => {
221
+ // If component is not resolved yet, resolve it
222
+ if (typeof Component === 'function' && !Component.options) {
223
+ Component = await Component()
224
+ }
225
+ // Sanitize it and save it
226
+ const _Component = applySSRData(sanitizeComponent(Component), NUXT.data ? NUXT.data[index] : null)
227
+ match.components[key] = _Component
228
+ return _Component
229
+ })
230
+ }
231
+
232
+ function callMiddleware (Components, context, layout) {
233
+ let midd = ["i18n"]
234
+ let unknownMiddleware = false
235
+
236
+ // If layout is undefined, only call global middleware
237
+ if (typeof layout !== 'undefined') {
238
+ midd = [] // Exclude global middleware if layout defined (already called before)
239
+ layout = sanitizeComponent(layout)
240
+ if (layout.options.middleware) {
241
+ midd = midd.concat(layout.options.middleware)
242
+ }
243
+ Components.forEach((Component) => {
244
+ if (Component.options.middleware) {
245
+ midd = midd.concat(Component.options.middleware)
246
+ }
247
+ })
248
+ }
249
+
250
+ midd = midd.map((name) => {
251
+ if (typeof name === 'function') {
252
+ return name
253
+ }
254
+ if (typeof middleware[name] !== 'function') {
255
+ unknownMiddleware = true
256
+ this.error({ statusCode: 500, message: 'Unknown middleware ' + name })
257
+ }
258
+ return middleware[name]
259
+ })
260
+
261
+ if (unknownMiddleware) {
262
+ return
263
+ }
264
+ return middlewareSeries(midd, context)
265
+ }
266
+
267
+ async function render (to, from, next) {
268
+ if (this._routeChanged === false && this._paramChanged === false && this._queryChanged === false) {
269
+ return next()
270
+ }
271
+ // Handle first render on SPA mode
272
+ let spaFallback = false
273
+ if (to === from) {
274
+ _lastPaths = []
275
+ spaFallback = true
276
+ } else {
277
+ const fromMatches = []
278
+ _lastPaths = getMatchedComponents(from, fromMatches).map((Component, i) => {
279
+ return compile(from.matched[fromMatches[i]].path)(from.params)
280
+ })
281
+ }
282
+
283
+ // nextCalled is true when redirected
284
+ let nextCalled = false
285
+ const _next = (path) => {
286
+ if (from.path === path.path && this.$loading.finish) {
287
+ this.$loading.finish()
288
+ }
289
+
290
+ if (from.path !== path.path && this.$loading.pause) {
291
+ this.$loading.pause()
292
+ }
293
+
294
+ if (nextCalled) {
295
+ return
296
+ }
297
+
298
+ nextCalled = true
299
+ next(path)
300
+ }
301
+
302
+ // Update context
303
+ await setContext(app, {
304
+ route: to,
305
+ from,
306
+ next: _next.bind(this)
307
+ })
308
+ this._dateLastError = app.nuxt.dateErr
309
+ this._hadError = Boolean(app.nuxt.err)
310
+
311
+ // Get route's matched components
312
+ const matches = []
313
+ const Components = getMatchedComponents(to, matches)
314
+
315
+ // If no Components matched, generate 404
316
+ if (!Components.length) {
317
+ // Default layout
318
+ await callMiddleware.call(this, Components, app.context)
319
+ if (nextCalled) {
320
+ return
321
+ }
322
+
323
+ // Load layout for error page
324
+ const errorLayout = (NuxtError.options || NuxtError).layout
325
+ const layout = await this.loadLayout(
326
+ typeof errorLayout === 'function'
327
+ ? errorLayout.call(NuxtError, app.context)
328
+ : errorLayout
329
+ )
330
+
331
+ await callMiddleware.call(this, Components, app.context, layout)
332
+ if (nextCalled) {
333
+ return
334
+ }
335
+
336
+ // Show error page
337
+ app.context.error({ statusCode: 404, message: 'This page could not be found' })
338
+ return next()
339
+ }
340
+
341
+ // Update ._data and other properties if hot reloaded
342
+ Components.forEach((Component) => {
343
+ if (Component._Ctor && Component._Ctor.options) {
344
+ Component.options.asyncData = Component._Ctor.options.asyncData
345
+ Component.options.fetch = Component._Ctor.options.fetch
346
+ }
347
+ })
348
+
349
+ // Apply transitions
350
+ this.setTransitions(mapTransitions(Components, to, from))
351
+
352
+ try {
353
+ // Call middleware
354
+ await callMiddleware.call(this, Components, app.context)
355
+ if (nextCalled) {
356
+ return
357
+ }
358
+ if (app.context._errored) {
359
+ return next()
360
+ }
361
+
362
+ // Set layout
363
+ let layout = Components[0].options.layout
364
+ if (typeof layout === 'function') {
365
+ layout = layout(app.context)
366
+ }
367
+ layout = await this.loadLayout(layout)
368
+
369
+ // Call middleware for layout
370
+ await callMiddleware.call(this, Components, app.context, layout)
371
+ if (nextCalled) {
372
+ return
373
+ }
374
+ if (app.context._errored) {
375
+ return next()
376
+ }
377
+
378
+ // Call .validate()
379
+ let isValid = true
380
+ try {
381
+ for (const Component of Components) {
382
+ if (typeof Component.options.validate !== 'function') {
383
+ continue
384
+ }
385
+
386
+ isValid = await Component.options.validate(app.context)
387
+
388
+ if (!isValid) {
389
+ break
390
+ }
391
+ }
392
+ } catch (validationError) {
393
+ // ...If .validate() threw an error
394
+ this.error({
395
+ statusCode: validationError.statusCode || '500',
396
+ message: validationError.message
397
+ })
398
+ return next()
399
+ }
400
+
401
+ // ...If .validate() returned false
402
+ if (!isValid) {
403
+ this.error({ statusCode: 404, message: 'This page could not be found' })
404
+ return next()
405
+ }
406
+
407
+ let instances
408
+ // Call asyncData & fetch hooks on components matched by the route.
409
+ await Promise.all(Components.map(async (Component, i) => {
410
+ // Check if only children route changed
411
+ Component._path = compile(to.matched[matches[i]].path)(to.params)
412
+ Component._dataRefresh = false
413
+ const childPathChanged = Component._path !== _lastPaths[i]
414
+ // Refresh component (call asyncData & fetch) when:
415
+ // Route path changed part includes current component
416
+ // Or route param changed part includes current component and watchParam is not `false`
417
+ // Or route query is changed and watchQuery returns `true`
418
+ if (this._routeChanged && childPathChanged) {
419
+ Component._dataRefresh = true
420
+ } else if (this._paramChanged && childPathChanged) {
421
+ const watchParam = Component.options.watchParam
422
+ Component._dataRefresh = watchParam !== false
423
+ } else if (this._queryChanged) {
424
+ const watchQuery = Component.options.watchQuery
425
+ if (watchQuery === true) {
426
+ Component._dataRefresh = true
427
+ } else if (Array.isArray(watchQuery)) {
428
+ Component._dataRefresh = watchQuery.some(key => this._diffQuery[key])
429
+ } else if (typeof watchQuery === 'function') {
430
+ if (!instances) {
431
+ instances = getMatchedComponentsInstances(to)
432
+ }
433
+ Component._dataRefresh = watchQuery.apply(instances[i], [to.query, from.query])
434
+ }
435
+ }
436
+ if (!this._hadError && this._isMounted && !Component._dataRefresh) {
437
+ return
438
+ }
439
+
440
+ const promises = []
441
+
442
+ const hasAsyncData = (
443
+ Component.options.asyncData &&
444
+ typeof Component.options.asyncData === 'function'
445
+ )
446
+
447
+ const hasFetch = Boolean(Component.options.fetch) && Component.options.fetch.length
448
+
449
+ const loadingIncrease = (hasAsyncData && hasFetch) ? 30 : 45
450
+
451
+ // Call asyncData(context)
452
+ if (hasAsyncData) {
453
+ const promise = promisify(Component.options.asyncData, app.context)
454
+
455
+ promise.then((asyncDataResult) => {
456
+ applyAsyncData(Component, asyncDataResult)
457
+
458
+ if (this.$loading.increase) {
459
+ this.$loading.increase(loadingIncrease)
460
+ }
461
+ })
462
+ promises.push(promise)
463
+ }
464
+
465
+ // Check disabled page loading
466
+ this.$loading.manual = Component.options.loading === false
467
+
468
+ // Call fetch(context)
469
+ if (hasFetch) {
470
+ let p = Component.options.fetch(app.context)
471
+ if (!p || (!(p instanceof Promise) && (typeof p.then !== 'function'))) {
472
+ p = Promise.resolve(p)
473
+ }
474
+ p.then((fetchResult) => {
475
+ if (this.$loading.increase) {
476
+ this.$loading.increase(loadingIncrease)
477
+ }
478
+ })
479
+ promises.push(p)
480
+ }
481
+
482
+ return Promise.all(promises)
483
+ }))
484
+
485
+ // If not redirected
486
+ if (!nextCalled) {
487
+ if (this.$loading.finish && !this.$loading.manual) {
488
+ this.$loading.finish()
489
+ }
490
+
491
+ next()
492
+ }
493
+ } catch (err) {
494
+ const error = err || {}
495
+ if (error.message === 'ERR_REDIRECT') {
496
+ return this.$nuxt.$emit('routeChanged', to, from, error)
497
+ }
498
+ _lastPaths = []
499
+
500
+ globalHandleError(error)
501
+
502
+ // Load error layout
503
+ let layout = (NuxtError.options || NuxtError).layout
504
+ if (typeof layout === 'function') {
505
+ layout = layout(app.context)
506
+ }
507
+ await this.loadLayout(layout)
508
+
509
+ this.error(error)
510
+ this.$nuxt.$emit('routeChanged', to, from, error)
511
+ next()
512
+ }
513
+ }
514
+
515
+ // Fix components format in matched, it's due to code-splitting of vue-router
516
+ function normalizeComponents (to, ___) {
517
+ flatMapComponents(to, (Component, _, match, key) => {
518
+ if (typeof Component === 'object' && !Component.options) {
519
+ // Updated via vue-router resolveAsyncComponents()
520
+ Component = Vue.extend(Component)
521
+ Component._Ctor = Component
522
+ match.components[key] = Component
523
+ }
524
+ return Component
525
+ })
526
+ }
527
+
528
+ function setLayoutForNextPage (to) {
529
+ // Set layout
530
+ let hasError = Boolean(this.$options.nuxt.err)
531
+ if (this._hadError && this._dateLastError === this.$options.nuxt.dateErr) {
532
+ hasError = false
533
+ }
534
+ let layout = hasError
535
+ ? (NuxtError.options || NuxtError).layout
536
+ : to.matched[0].components.default.options.layout
537
+
538
+ if (typeof layout === 'function') {
539
+ layout = layout(app.context)
540
+ }
541
+
542
+ this.setLayout(layout)
543
+ }
544
+
545
+ function checkForErrors (app) {
546
+ // Hide error component if no error
547
+ if (app._hadError && app._dateLastError === app.$options.nuxt.dateErr) {
548
+ app.error()
549
+ }
550
+ }
551
+
552
+ // When navigating on a different route but the same component is used, Vue.js
553
+ // Will not update the instance data, so we have to update $data ourselves
554
+ function fixPrepatch (to, ___) {
555
+ if (this._routeChanged === false && this._paramChanged === false && this._queryChanged === false) {
556
+ return
557
+ }
558
+
559
+ const instances = getMatchedComponentsInstances(to)
560
+ const Components = getMatchedComponents(to)
561
+
562
+ let triggerScroll = false
563
+
564
+ Vue.nextTick(() => {
565
+ instances.forEach((instance, i) => {
566
+ if (!instance || instance._isDestroyed) {
567
+ return
568
+ }
569
+
570
+ if (
571
+ instance.constructor._dataRefresh &&
572
+ Components[i] === instance.constructor &&
573
+ instance.$vnode.data.keepAlive !== true &&
574
+ typeof instance.constructor.options.data === 'function'
575
+ ) {
576
+ const newData = instance.constructor.options.data.call(instance)
577
+ for (const key in newData) {
578
+ Vue.set(instance.$data, key, newData[key])
579
+ }
580
+
581
+ triggerScroll = true
582
+ }
583
+ })
584
+
585
+ if (triggerScroll) {
586
+ // Ensure to trigger scroll event after calling scrollBehavior
587
+ window.$nuxt.$nextTick(() => {
588
+ window.$nuxt.$emit('triggerScroll')
589
+ })
590
+ }
591
+
592
+ checkForErrors(this)
593
+
594
+ // Hot reloading
595
+ setTimeout(() => hotReloadAPI(this), 100)
596
+ })
597
+ }
598
+
599
+ function nuxtReady (_app) {
600
+ window.onNuxtReadyCbs.forEach((cb) => {
601
+ if (typeof cb === 'function') {
602
+ cb(_app)
603
+ }
604
+ })
605
+ // Special JSDOM
606
+ if (typeof window._onNuxtLoaded === 'function') {
607
+ window._onNuxtLoaded(_app)
608
+ }
609
+ // Add router hooks
610
+ router.afterEach((to, from) => {
611
+ // Wait for fixPrepatch + $data updates
612
+ Vue.nextTick(() => _app.$nuxt.$emit('routeChanged', to, from))
613
+ })
614
+ }
615
+
616
+ const noopData = () => { return {} }
617
+ const noopFetch = () => {}
618
+
619
+ // Special hot reload with asyncData(context)
620
+ function getNuxtChildComponents ($parent, $components = []) {
621
+ $parent.$children.forEach(($child) => {
622
+ if ($child.$vnode && $child.$vnode.data.nuxtChild && !$components.find(c =>(c.$options.__file === $child.$options.__file))) {
623
+ $components.push($child)
624
+ }
625
+ if ($child.$children && $child.$children.length) {
626
+ getNuxtChildComponents($child, $components)
627
+ }
628
+ })
629
+
630
+ return $components
631
+ }
632
+
633
+ function hotReloadAPI(_app) {
634
+ if (!module.hot) return
635
+
636
+ let $components = getNuxtChildComponents(_app.$nuxt, [])
637
+
638
+ $components.forEach(addHotReload.bind(_app))
639
+ }
640
+
641
+ function addHotReload ($component, depth) {
642
+ if ($component.$vnode.data._hasHotReload) return
643
+ $component.$vnode.data._hasHotReload = true
644
+
645
+ var _forceUpdate = $component.$forceUpdate.bind($component.$parent)
646
+
647
+ $component.$vnode.context.$forceUpdate = async () => {
648
+ let Components = getMatchedComponents(router.currentRoute)
649
+ let Component = Components[depth]
650
+ if (!Component) {
651
+ return _forceUpdate()
652
+ }
653
+ if (typeof Component === 'object' && !Component.options) {
654
+ // Updated via vue-router resolveAsyncComponents()
655
+ Component = Vue.extend(Component)
656
+ Component._Ctor = Component
657
+ }
658
+ this.error()
659
+ let promises = []
660
+ const next = function (path) {
661
+ this.$loading.finish && this.$loading.finish()
662
+ router.push(path)
663
+ }
664
+ await setContext(app, {
665
+ route: router.currentRoute,
666
+ isHMR: true,
667
+ next: next.bind(this)
668
+ })
669
+ const context = app.context
670
+
671
+ if (this.$loading.start && !this.$loading.manual) {
672
+ this.$loading.start()
673
+ }
674
+
675
+ callMiddleware.call(this, Components, context)
676
+ .then(() => {
677
+ // If layout changed
678
+ if (depth !== 0) {
679
+ return
680
+ }
681
+
682
+ let layout = Component.options.layout || 'default'
683
+ if (typeof layout === 'function') {
684
+ layout = layout(context)
685
+ }
686
+ if (this.layoutName === layout) {
687
+ return
688
+ }
689
+ let promise = this.loadLayout(layout)
690
+ promise.then(() => {
691
+ this.setLayout(layout)
692
+ Vue.nextTick(() => hotReloadAPI(this))
693
+ })
694
+ return promise
695
+ })
696
+
697
+ .then(() => {
698
+ return callMiddleware.call(this, Components, context, this.layout)
699
+ })
700
+
701
+ .then(() => {
702
+ // Call asyncData(context)
703
+ let pAsyncData = promisify(Component.options.asyncData || noopData, context)
704
+ pAsyncData.then((asyncDataResult) => {
705
+ applyAsyncData(Component, asyncDataResult)
706
+ this.$loading.increase && this.$loading.increase(30)
707
+ })
708
+ promises.push(pAsyncData)
709
+
710
+ // Call fetch()
711
+ Component.options.fetch = Component.options.fetch || noopFetch
712
+ let pFetch = Component.options.fetch.length && Component.options.fetch(context)
713
+ if (!pFetch || (!(pFetch instanceof Promise) && (typeof pFetch.then !== 'function'))) { pFetch = Promise.resolve(pFetch) }
714
+ pFetch.then(() => this.$loading.increase && this.$loading.increase(30))
715
+ promises.push(pFetch)
716
+
717
+ return Promise.all(promises)
718
+ })
719
+ .then(() => {
720
+ this.$loading.finish && this.$loading.finish()
721
+ _forceUpdate()
722
+ setTimeout(() => hotReloadAPI(this), 100)
723
+ })
724
+ }
725
+ }
726
+
727
+ async function mountApp (__app) {
728
+ // Set global variables
729
+ app = __app.app
730
+ router = __app.router
731
+ store = __app.store
732
+
733
+ // Create Vue instance
734
+ const _app = new Vue(app)
735
+
736
+ // Mounts Vue app to DOM element
737
+ const mount = () => {
738
+ _app.$mount('#app')
739
+
740
+ // Add afterEach router hooks
741
+ router.afterEach(normalizeComponents)
742
+
743
+ router.afterEach(setLayoutForNextPage.bind(_app))
744
+
745
+ router.afterEach(fixPrepatch.bind(_app))
746
+
747
+ // Listen for first Vue update
748
+ Vue.nextTick(() => {
749
+ // Call window.{{globals.readyCallback}} callbacks
750
+ nuxtReady(_app)
751
+
752
+ // Enable hot reloading
753
+ hotReloadAPI(_app)
754
+ })
755
+ }
756
+
757
+ // Resolve route components
758
+ const Components = await Promise.all(resolveComponents(app.context.route))
759
+
760
+ // Enable transitions
761
+ _app.setTransitions = _app.$options.nuxt.setTransitions.bind(_app)
762
+ if (Components.length) {
763
+ _app.setTransitions(mapTransitions(Components, router.currentRoute))
764
+ _lastPaths = router.currentRoute.matched.map(route => compile(route.path)(router.currentRoute.params))
765
+ }
766
+
767
+ // Initialize error handler
768
+ _app.$loading = {} // To avoid error while _app.$nuxt does not exist
769
+ if (NUXT.error) {
770
+ _app.error(NUXT.error)
771
+ }
772
+
773
+ // Add beforeEach router hooks
774
+ router.beforeEach(loadAsyncComponents.bind(_app))
775
+ router.beforeEach(render.bind(_app))
776
+
777
+ // Fix in static: remove trailing slash to force hydration
778
+ // Full static, if server-rendered: hydrate, to allow custom redirect to generated page
779
+
780
+ // Fix in static: remove trailing slash to force hydration
781
+ if (NUXT.serverRendered && isSamePath(NUXT.routePath, _app.context.route.path)) {
782
+ return mount()
783
+ }
784
+
785
+ // First render on client-side
786
+ const clientFirstMount = () => {
787
+ normalizeComponents(router.currentRoute, router.currentRoute)
788
+ setLayoutForNextPage.call(_app, router.currentRoute)
789
+ checkForErrors(_app)
790
+ // Don't call fixPrepatch.call(_app, router.currentRoute, router.currentRoute) since it's first render
791
+ mount()
792
+ }
793
+
794
+ // fix: force next tick to avoid having same timestamp when an error happen on spa fallback
795
+ await new Promise(resolve => setTimeout(resolve, 0))
796
+ render.call(_app, router.currentRoute, router.currentRoute, (path) => {
797
+ // If not redirected
798
+ if (!path) {
799
+ clientFirstMount()
800
+ return
801
+ }
802
+
803
+ // Add a one-time afterEach hook to
804
+ // mount the app wait for redirect and route gets resolved
805
+ const unregisterHook = router.afterEach((to, from) => {
806
+ unregisterHook()
807
+ clientFirstMount()
808
+ })
809
+
810
+ // Push the path and let route to be resolved
811
+ router.push(path, undefined, (err) => {
812
+ if (err) {
813
+ errorHandler(err)
814
+ }
815
+ })
816
+ })
817
+ }