├── .circleci └── config.yml ├── .github ├── CODEOWNERS └── pull_request_template.md ├── .gitignore ├── .nuxt ├── App.js ├── client.js ├── components │ ├── no-ssr.js │ ├── nuxt-build-indicator.vue │ ├── nuxt-child.js │ ├── nuxt-error.vue │ ├── nuxt-link.client.js │ ├── nuxt-link.server.js │ ├── nuxt-loading.vue │ └── nuxt.js ├── dist │ ├── client │ │ ├── 08fd1945017a9e6f7c71.js │ │ ├── 21cc65e130e32d4b5c6c.js │ │ ├── 4bff0aa5c468a6e516c5.js │ │ ├── 51be53da316e3efc6a25.js │ │ ├── LICENSES │ │ └── e2ed95a5f585d36d08fb.js │ └── server │ │ ├── client.manifest.json │ │ ├── f1e952c8bf78d43839d8.js │ │ ├── f1e952c8bf78d43839d8.js.map │ │ ├── index.spa.html │ │ ├── index.ssr.html │ │ ├── server.js │ │ ├── server.js.map │ │ └── server.manifest.json ├── empty.js ├── index.js ├── layouts │ └── default.vue ├── lib.module.plugin.52b4b1c3.js ├── loading.html ├── middleware.js ├── router.js ├── server.js ├── utils.js └── views │ ├── app.template.html │ └── error.html ├── .prettierignore ├── .prettierrc ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── README.md ├── lib ├── module.js ├── module.middleware.js └── module.plugin.js ├── package-lock.json ├── package.json ├── test ├── fixture │ ├── nuxt.config.js │ └── pages │ │ └── index.vue ├── system │ └── module.test.js └── unit │ ├── module.middleware.test.js │ └── module.test.js └── yarn.lock /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Generated by create-nuxt-module 2 | version: 2 3 | jobs: 4 | build: 5 | docker: 6 | - image: circleci/node:10.17.0-browsers 7 | 8 | working_directory: ~/app 9 | 10 | steps: 11 | - checkout 12 | 13 | - restore_cache: 14 | keys: 15 | - v1-dependencies-{{ checksum "package.json" }} 16 | 17 | - run: yarn install 18 | 19 | - save_cache: 20 | paths: 21 | - node_modules 22 | key: v1-dependencies-{{ checksum "package.json" }} 23 | 24 | - run: NODE_ENV=test yarn test:coverage 25 | - store_artifacts: 26 | path: ~/app/coverage/lcov-apprt/ 27 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # This is a comment. 2 | # Each line is a file pattern followed by one or more owners. 3 | 4 | # These owners will be the default owners for everything in 5 | # the repo. Unless a later match takes precedence, 6 | # @S0ulf7y and @vittorioe will be requested for 7 | # review when someone opens a pull request. 8 | * @S0ulf7y @vittorioe 9 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # Pull-Request # 2 | 3 | ## Instructions for the test: ## 4 | *Please describe* 5 | 6 | ## Expected result: ## 7 | *Please describe* 8 | 9 | ## Changes ## 10 | *Please describe* 11 | 12 | ## Screenshots of the changes ## 13 | *Please insert here* 14 | 15 | ## Installation instructions ## 16 | *(No special instructions needed)* 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next -------------------------------------------------------------------------------- /.nuxt/App.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import NuxtLoading from './components/nuxt-loading.vue' 3 | 4 | import _6f6c098b from './layouts/default.vue' 5 | 6 | const layouts = { "_default": _6f6c098b }// eslint-disable-line 7 | 8 | export default { 9 | /* eslint-disable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, space-before-function-paren */ 10 | head: {"meta":[],"link":[],"style":[],"script":[]}, 11 | /* eslint-enable quotes, semi, indent, comma-spacing, key-spacing, object-curly-spacing, space-before-function-paren */ 12 | render(h, props) { 13 | const loadingEl = h('NuxtLoading', { ref: 'loading' }) 14 | const layoutEl = h(this.layout || 'nuxt') 15 | const templateEl = h('div', { 16 | domProps: { 17 | id: '__layout' 18 | }, 19 | key: this.layoutName 20 | }, [ layoutEl ]) 21 | 22 | const transitionEl = h('transition', { 23 | props: { 24 | name: 'layout', 25 | mode: 'out-in' 26 | }, 27 | on: { 28 | beforeEnter(el) { 29 | // Ensure to trigger scroll event after calling scrollBehavior 30 | window.$nuxt.$nextTick(() => { 31 | window.$nuxt.$emit('triggerScroll') 32 | }) 33 | } 34 | } 35 | }, [ templateEl ]) 36 | 37 | return h('div', { 38 | domProps: { 39 | id: '__nuxt' 40 | } 41 | }, [loadingEl, transitionEl]) 42 | }, 43 | data: () => ({ 44 | isOnline: true, 45 | layout: null, 46 | layoutName: '' 47 | }), 48 | beforeCreate() { 49 | Vue.util.defineReactive(this, 'nuxt', this.$options.nuxt) 50 | }, 51 | created() { 52 | // Add this.$nuxt in child instances 53 | Vue.prototype.$nuxt = this 54 | // add to window so we can listen when ready 55 | if (process.client) { 56 | window.$nuxt = this 57 | this.refreshOnlineStatus() 58 | // Setup the listeners 59 | window.addEventListener('online', this.refreshOnlineStatus) 60 | window.addEventListener('offline', this.refreshOnlineStatus) 61 | } 62 | // Add $nuxt.error() 63 | this.error = this.nuxt.error 64 | }, 65 | 66 | mounted() { 67 | this.$loading = this.$refs.loading 68 | }, 69 | watch: { 70 | 'nuxt.err': 'errorChanged' 71 | }, 72 | 73 | computed: { 74 | isOffline() { 75 | return !this.isOnline 76 | } 77 | }, 78 | methods: { 79 | refreshOnlineStatus() { 80 | if (process.client) { 81 | if (typeof window.navigator.onLine === 'undefined') { 82 | // If the browser doesn't support connection status reports 83 | // assume that we are online because most apps' only react 84 | // when they now that the connection has been interrupted 85 | this.isOnline = true 86 | } else { 87 | this.isOnline = window.navigator.onLine 88 | } 89 | } 90 | }, 91 | 92 | errorChanged() { 93 | if (this.nuxt.err && this.$loading) { 94 | if (this.$loading.fail) this.$loading.fail() 95 | if (this.$loading.finish) this.$loading.finish() 96 | } 97 | }, 98 | 99 | setLayout(layout) { 100 | if (!layout || !layouts['_' + layout]) { 101 | layout = 'default' 102 | } 103 | this.layoutName = layout 104 | this.layout = layouts['_' + layout] 105 | return this.layout 106 | }, 107 | loadLayout(layout) { 108 | if (!layout || !layouts['_' + layout]) { 109 | layout = 'default' 110 | } 111 | return Promise.resolve(layouts['_' + layout]) 112 | } 113 | }, 114 | components: { 115 | NuxtLoading 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /.nuxt/client.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import fetch from 'unfetch' 3 | import middleware from './middleware.js' 4 | import { 5 | applyAsyncData, 6 | sanitizeComponent, 7 | resolveRouteComponents, 8 | getMatchedComponents, 9 | getMatchedComponentsInstances, 10 | flatMapComponents, 11 | setContext, 12 | middlewareSeries, 13 | promisify, 14 | getLocation, 15 | compile, 16 | getQueryDiff, 17 | globalHandleError 18 | } from './utils.js' 19 | import { createApp, NuxtError } from './index.js' 20 | import NuxtLink from './components/nuxt-link.client.js' // should be included after ./index.js 21 | 22 | // Component: 23 | Vue.component(NuxtLink.name, NuxtLink) 24 | Vue.component('NLink', NuxtLink) 25 | 26 | if (!global.fetch) { global.fetch = fetch } 27 | 28 | // Global shared references 29 | let _lastPaths = [] 30 | let app 31 | let router 32 | 33 | // Try to rehydrate SSR data from window 34 | const NUXT = window.__NUXT__ || {} 35 | 36 | Object.assign(Vue.config, {"silent":true,"performance":false})// eslint-disable-line 37 | 38 | const errorHandler = Vue.config.errorHandler || console.error 39 | 40 | // Create and mount App 41 | createApp().then(mountApp).catch(errorHandler) 42 | 43 | function componentOption(component, key, ...args) { 44 | if (!component || !component.options || !component.options[key]) { 45 | return {} 46 | } 47 | const option = component.options[key] 48 | if (typeof option === 'function') { 49 | return option(...args) 50 | } 51 | return option 52 | } 53 | 54 | function mapTransitions(Components, to, from) { 55 | const componentTransitions = (component) => { 56 | const transition = componentOption(component, 'transition', to, from) || {} 57 | return (typeof transition === 'string' ? { name: transition } : transition) 58 | } 59 | 60 | return Components.map((Component) => { 61 | // Clone original object to prevent overrides 62 | const transitions = Object.assign({}, componentTransitions(Component)) 63 | 64 | // Combine transitions & prefer `leave` transitions of 'from' route 65 | if (from && from.matched.length && from.matched[0].components.default) { 66 | const fromTransitions = componentTransitions(from.matched[0].components.default) 67 | Object.keys(fromTransitions) 68 | .filter(key => fromTransitions[key] && key.toLowerCase().includes('leave')) 69 | .forEach((key) => { transitions[key] = fromTransitions[key] }) 70 | } 71 | 72 | return transitions 73 | }) 74 | } 75 | 76 | async function loadAsyncComponents(to, from, next) { 77 | // Check if route path changed (this._pathChanged), only if the page is not an error (for validate()) 78 | this._pathChanged = Boolean(app.nuxt.err) || from.path !== to.path 79 | this._queryChanged = JSON.stringify(to.query) !== JSON.stringify(from.query) 80 | this._diffQuery = (this._queryChanged ? getQueryDiff(to.query, from.query) : []) 81 | 82 | if (this._pathChanged && this.$loading.start && !this.$loading.manual) { 83 | this.$loading.start() 84 | } 85 | 86 | try { 87 | const Components = await resolveRouteComponents(to) 88 | 89 | if (!this._pathChanged && this._queryChanged) { 90 | // Add a marker on each component that it needs to refresh or not 91 | const startLoader = Components.some((Component) => { 92 | const watchQuery = Component.options.watchQuery 93 | if (watchQuery === true) return true 94 | if (Array.isArray(watchQuery)) { 95 | return watchQuery.some(key => this._diffQuery[key]) 96 | } 97 | return false 98 | }) 99 | if (startLoader && this.$loading.start && !this.$loading.manual) { 100 | this.$loading.start() 101 | } 102 | } 103 | 104 | // Call next() 105 | next() 106 | } catch (error) { 107 | const err = error || {} 108 | const statusCode = err.statusCode || err.status || (err.response && err.response.status) || 500 109 | const message = err.message || '' 110 | 111 | // Handle chunk loading errors 112 | // This may be due to a new deployment or a network problem 113 | if (/^Loading( CSS)? chunk (\d)+ failed\./.test(message)) { 114 | window.location.reload(true /* skip cache */) 115 | return // prevent error page blinking for user 116 | } 117 | 118 | this.error({ statusCode, message }) 119 | this.$nuxt.$emit('routeChanged', to, from, err) 120 | next() 121 | } 122 | } 123 | 124 | function applySSRData(Component, ssrData) { 125 | if (NUXT.serverRendered && ssrData) { 126 | applyAsyncData(Component, ssrData) 127 | } 128 | Component._Ctor = Component 129 | return Component 130 | } 131 | 132 | // Get matched components 133 | function resolveComponents(router) { 134 | const path = getLocation(router.options.base, router.options.mode) 135 | 136 | return flatMapComponents(router.match(path), async (Component, _, match, key, index) => { 137 | // If component is not resolved yet, resolve it 138 | if (typeof Component === 'function' && !Component.options) { 139 | Component = await Component() 140 | } 141 | // Sanitize it and save it 142 | const _Component = applySSRData(sanitizeComponent(Component), NUXT.data ? NUXT.data[index] : null) 143 | match.components[key] = _Component 144 | return _Component 145 | }) 146 | } 147 | 148 | function callMiddleware(Components, context, layout) { 149 | let midd = []// eslint-disable-line 150 | let unknownMiddleware = false 151 | 152 | // If layout is undefined, only call global middleware 153 | if (typeof layout !== 'undefined') { 154 | midd = [] // Exclude global middleware if layout defined (already called before) 155 | layout = sanitizeComponent(layout) 156 | if (layout.options.middleware) { 157 | midd = midd.concat(layout.options.middleware) 158 | } 159 | Components.forEach((Component) => { 160 | if (Component.options.middleware) { 161 | midd = midd.concat(Component.options.middleware) 162 | } 163 | }) 164 | } 165 | 166 | midd = midd.map((name) => { 167 | if (typeof name === 'function') return name 168 | if (typeof middleware[name] !== 'function') { 169 | unknownMiddleware = true 170 | this.error({ statusCode: 500, message: 'Unknown middleware ' + name }) 171 | } 172 | return middleware[name] 173 | }) 174 | 175 | if (unknownMiddleware) return 176 | return middlewareSeries(midd, context) 177 | } 178 | 179 | async function render(to, from, next) { 180 | if (this._pathChanged === false && this._queryChanged === false) return next() 181 | // Handle first render on SPA mode 182 | if (to === from) _lastPaths = [] 183 | else { 184 | const fromMatches = [] 185 | _lastPaths = getMatchedComponents(from, fromMatches).map((Component, i) => { 186 | return compile(from.matched[fromMatches[i]].path)(from.params) 187 | }) 188 | } 189 | 190 | // nextCalled is true when redirected 191 | let nextCalled = false 192 | const _next = (path) => { 193 | if (from.path === path.path && this.$loading.finish) { 194 | this.$loading.finish() 195 | } 196 | 197 | if (from.path !== path.path && this.$loading.pause) { 198 | this.$loading.pause() 199 | } 200 | 201 | if (nextCalled) return 202 | nextCalled = true 203 | next(path) 204 | } 205 | 206 | // Update context 207 | await setContext(app, { 208 | route: to, 209 | from, 210 | next: _next.bind(this) 211 | }) 212 | this._dateLastError = app.nuxt.dateErr 213 | this._hadError = Boolean(app.nuxt.err) 214 | 215 | // Get route's matched components 216 | const matches = [] 217 | const Components = getMatchedComponents(to, matches) 218 | 219 | // If no Components matched, generate 404 220 | if (!Components.length) { 221 | // Default layout 222 | await callMiddleware.call(this, Components, app.context) 223 | if (nextCalled) return 224 | // Load layout for error page 225 | const layout = await this.loadLayout( 226 | typeof NuxtError.layout === 'function' 227 | ? NuxtError.layout(app.context) 228 | : NuxtError.layout 229 | ) 230 | await callMiddleware.call(this, Components, app.context, layout) 231 | if (nextCalled) return 232 | // Show error page 233 | app.context.error({ statusCode: 404, message: `This page could not be found` }) 234 | return next() 235 | } 236 | 237 | // Update ._data and other properties if hot reloaded 238 | Components.forEach((Component) => { 239 | if (Component._Ctor && Component._Ctor.options) { 240 | Component.options.asyncData = Component._Ctor.options.asyncData 241 | Component.options.fetch = Component._Ctor.options.fetch 242 | } 243 | }) 244 | 245 | // Apply transitions 246 | this.setTransitions(mapTransitions(Components, to, from)) 247 | 248 | try { 249 | // Call middleware 250 | await callMiddleware.call(this, Components, app.context) 251 | if (nextCalled) return 252 | if (app.context._errored) return next() 253 | 254 | // Set layout 255 | let layout = Components[0].options.layout 256 | if (typeof layout === 'function') { 257 | layout = layout(app.context) 258 | } 259 | layout = await this.loadLayout(layout) 260 | 261 | // Call middleware for layout 262 | await callMiddleware.call(this, Components, app.context, layout) 263 | if (nextCalled) return 264 | if (app.context._errored) return next() 265 | 266 | // Call .validate() 267 | let isValid = true 268 | try { 269 | for (const Component of Components) { 270 | if (typeof Component.options.validate !== 'function') { 271 | continue 272 | } 273 | 274 | isValid = await Component.options.validate(app.context) 275 | 276 | if (!isValid) { 277 | break 278 | } 279 | } 280 | } catch (validationError) { 281 | // ...If .validate() threw an error 282 | this.error({ 283 | statusCode: validationError.statusCode || '500', 284 | message: validationError.message 285 | }) 286 | return next() 287 | } 288 | 289 | // ...If .validate() returned false 290 | if (!isValid) { 291 | this.error({ statusCode: 404, message: `This page could not be found` }) 292 | return next() 293 | } 294 | 295 | // Call asyncData & fetch hooks on components matched by the route. 296 | await Promise.all(Components.map((Component, i) => { 297 | // Check if only children route changed 298 | Component._path = compile(to.matched[matches[i]].path)(to.params) 299 | Component._dataRefresh = false 300 | // Check if Component need to be refreshed (call asyncData & fetch) 301 | // Only if its slug has changed or is watch query changes 302 | if ((this._pathChanged && this._queryChanged) || Component._path !== _lastPaths[i]) { 303 | Component._dataRefresh = true 304 | } else if (!this._pathChanged && this._queryChanged) { 305 | const watchQuery = Component.options.watchQuery 306 | if (watchQuery === true) { 307 | Component._dataRefresh = true 308 | } else if (Array.isArray(watchQuery)) { 309 | Component._dataRefresh = watchQuery.some(key => this._diffQuery[key]) 310 | } 311 | } 312 | if (!this._hadError && this._isMounted && !Component._dataRefresh) { 313 | return Promise.resolve() 314 | } 315 | 316 | const promises = [] 317 | 318 | const hasAsyncData = ( 319 | Component.options.asyncData && 320 | typeof Component.options.asyncData === 'function' 321 | ) 322 | const hasFetch = Boolean(Component.options.fetch) 323 | 324 | const loadingIncrease = (hasAsyncData && hasFetch) ? 30 : 45 325 | 326 | // Call asyncData(context) 327 | if (hasAsyncData) { 328 | const promise = promisify(Component.options.asyncData, app.context) 329 | .then((asyncDataResult) => { 330 | applyAsyncData(Component, asyncDataResult) 331 | 332 | if (this.$loading.increase) { 333 | this.$loading.increase(loadingIncrease) 334 | } 335 | }) 336 | promises.push(promise) 337 | } 338 | 339 | // Check disabled page loading 340 | this.$loading.manual = Component.options.loading === false 341 | 342 | // Call fetch(context) 343 | if (hasFetch) { 344 | let p = Component.options.fetch(app.context) 345 | if (!p || (!(p instanceof Promise) && (typeof p.then !== 'function'))) { 346 | p = Promise.resolve(p) 347 | } 348 | p.then((fetchResult) => { 349 | if (this.$loading.increase) { 350 | this.$loading.increase(loadingIncrease) 351 | } 352 | }) 353 | promises.push(p) 354 | } 355 | 356 | return Promise.all(promises) 357 | })) 358 | 359 | // If not redirected 360 | if (!nextCalled) { 361 | if (this.$loading.finish && !this.$loading.manual) { 362 | this.$loading.finish() 363 | } 364 | 365 | next() 366 | } 367 | } catch (err) { 368 | const error = err || {} 369 | if (error.message === 'ERR_REDIRECT') { 370 | return this.$nuxt.$emit('routeChanged', to, from, error) 371 | } 372 | _lastPaths = [] 373 | 374 | globalHandleError(error) 375 | 376 | // Load error layout 377 | let layout = NuxtError.layout 378 | if (typeof layout === 'function') { 379 | layout = layout(app.context) 380 | } 381 | await this.loadLayout(layout) 382 | 383 | this.error(error) 384 | this.$nuxt.$emit('routeChanged', to, from, error) 385 | next() 386 | } 387 | } 388 | 389 | // Fix components format in matched, it's due to code-splitting of vue-router 390 | function normalizeComponents(to, ___) { 391 | flatMapComponents(to, (Component, _, match, key) => { 392 | if (typeof Component === 'object' && !Component.options) { 393 | // Updated via vue-router resolveAsyncComponents() 394 | Component = Vue.extend(Component) 395 | Component._Ctor = Component 396 | match.components[key] = Component 397 | } 398 | return Component 399 | }) 400 | } 401 | 402 | function showNextPage(to) { 403 | // Hide error component if no error 404 | if (this._hadError && this._dateLastError === this.$options.nuxt.dateErr) { 405 | this.error() 406 | } 407 | 408 | // Set layout 409 | let layout = this.$options.nuxt.err 410 | ? NuxtError.layout 411 | : to.matched[0].components.default.options.layout 412 | 413 | if (typeof layout === 'function') { 414 | layout = layout(app.context) 415 | } 416 | this.setLayout(layout) 417 | } 418 | 419 | // When navigating on a different route but the same component is used, Vue.js 420 | // Will not update the instance data, so we have to update $data ourselves 421 | function fixPrepatch(to, ___) { 422 | if (this._pathChanged === false && this._queryChanged === false) return 423 | 424 | const matches = [] 425 | const instances = getMatchedComponentsInstances(to, matches) 426 | const Components = getMatchedComponents(to, matches) 427 | 428 | Vue.nextTick(() => { 429 | instances.forEach((instance, i) => { 430 | if (!instance || instance._isDestroyed) return 431 | // if ( 432 | // !this._queryChanged && 433 | // to.matched[matches[i]].path.indexOf(':') === -1 && 434 | // to.matched[matches[i]].path.indexOf('*') === -1 435 | // ) return // If not a dynamic route, skip 436 | if ( 437 | instance.constructor._dataRefresh && 438 | Components[i] === instance.constructor && 439 | instance.$vnode.data.keepAlive !== true && 440 | typeof instance.constructor.options.data === 'function' 441 | ) { 442 | const newData = instance.constructor.options.data.call(instance) 443 | for (const key in newData) { 444 | Vue.set(instance.$data, key, newData[key]) 445 | } 446 | 447 | // Ensure to trigger scroll event after calling scrollBehavior 448 | window.$nuxt.$nextTick(() => { 449 | window.$nuxt.$emit('triggerScroll') 450 | }) 451 | } 452 | }) 453 | showNextPage.call(this, to) 454 | }) 455 | } 456 | 457 | function nuxtReady(_app) { 458 | window.onNuxtReadyCbs.forEach((cb) => { 459 | if (typeof cb === 'function') { 460 | cb(_app) 461 | } 462 | }) 463 | // Special JSDOM 464 | if (typeof window._onNuxtLoaded === 'function') { 465 | window._onNuxtLoaded(_app) 466 | } 467 | // Add router hooks 468 | router.afterEach((to, from) => { 469 | // Wait for fixPrepatch + $data updates 470 | Vue.nextTick(() => _app.$nuxt.$emit('routeChanged', to, from)) 471 | }) 472 | } 473 | 474 | async function mountApp(__app) { 475 | // Set global variables 476 | app = __app.app 477 | router = __app.router 478 | 479 | // Resolve route components 480 | const Components = await Promise.all(resolveComponents(router)) 481 | 482 | // Create Vue instance 483 | const _app = new Vue(app) 484 | 485 | // Load layout 486 | const layout = NUXT.layout || 'default' 487 | await _app.loadLayout(layout) 488 | _app.setLayout(layout) 489 | 490 | // Mounts Vue app to DOM element 491 | const mount = () => { 492 | _app.$mount('#__nuxt') 493 | 494 | // Add afterEach router hooks 495 | router.afterEach(normalizeComponents) 496 | router.afterEach(fixPrepatch.bind(_app)) 497 | 498 | // Listen for first Vue update 499 | Vue.nextTick(() => { 500 | // Call window.{{globals.readyCallback}} callbacks 501 | nuxtReady(_app) 502 | }) 503 | } 504 | 505 | // Enable transitions 506 | _app.setTransitions = _app.$options.nuxt.setTransitions.bind(_app) 507 | if (Components.length) { 508 | _app.setTransitions(mapTransitions(Components, router.currentRoute)) 509 | _lastPaths = router.currentRoute.matched.map(route => compile(route.path)(router.currentRoute.params)) 510 | } 511 | 512 | // Initialize error handler 513 | _app.$loading = {} // To avoid error while _app.$nuxt does not exist 514 | if (NUXT.error) _app.error(NUXT.error) 515 | 516 | // Add beforeEach router hooks 517 | router.beforeEach(loadAsyncComponents.bind(_app)) 518 | router.beforeEach(render.bind(_app)) 519 | 520 | // If page already is server rendered 521 | if (NUXT.serverRendered) { 522 | mount() 523 | return 524 | } 525 | 526 | // First render on client-side 527 | const clientFirstMount = () => { 528 | normalizeComponents(router.currentRoute, router.currentRoute) 529 | showNextPage.call(_app, router.currentRoute) 530 | // Don't call fixPrepatch.call(_app, router.currentRoute, router.currentRoute) since it's first render 531 | mount() 532 | } 533 | 534 | render.call(_app, router.currentRoute, router.currentRoute, (path) => { 535 | // If not redirected 536 | if (!path) { 537 | clientFirstMount() 538 | return 539 | } 540 | 541 | // Add a one-time afterEach hook to 542 | // mount the app wait for redirect and route gets resolved 543 | const unregisterHook = router.afterEach((to, from) => { 544 | unregisterHook() 545 | clientFirstMount() 546 | }) 547 | 548 | // Push the path and let route to be resolved 549 | router.push(path, undefined, (err) => { 550 | if (err) errorHandler(err) 551 | }) 552 | }) 553 | } 554 | -------------------------------------------------------------------------------- /.nuxt/components/no-ssr.js: -------------------------------------------------------------------------------- 1 | /* @vue/component 2 | ** From https://github.com/egoist/vue-no-ssr 3 | ** With the authorization of @egoist 4 | */ 5 | import NoSsr from 'vue-no-ssr' 6 | export default { 7 | ...NoSsr, 8 | name: 'NoSsr' 9 | } 10 | -------------------------------------------------------------------------------- /.nuxt/components/nuxt-build-indicator.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 125 | 126 | 156 | -------------------------------------------------------------------------------- /.nuxt/components/nuxt-child.js: -------------------------------------------------------------------------------- 1 | // @vue/component 2 | export default { 3 | name: 'NuxtChild', 4 | functional: true, 5 | props: { 6 | nuxtChildKey: { 7 | type: String, 8 | default: '' 9 | }, 10 | keepAlive: Boolean, 11 | keepAliveProps: { 12 | type: Object, 13 | default: undefined 14 | } 15 | }, 16 | render(h, { parent, data, props }) { 17 | data.nuxtChild = true 18 | const _parent = parent 19 | const transitions = parent.$nuxt.nuxt.transitions 20 | const defaultTransition = parent.$nuxt.nuxt.defaultTransition 21 | 22 | let depth = 0 23 | while (parent) { 24 | if (parent.$vnode && parent.$vnode.data.nuxtChild) { 25 | depth++ 26 | } 27 | parent = parent.$parent 28 | } 29 | data.nuxtChildDepth = depth 30 | const transition = transitions[depth] || defaultTransition 31 | const transitionProps = {} 32 | transitionsKeys.forEach((key) => { 33 | if (typeof transition[key] !== 'undefined') { 34 | transitionProps[key] = transition[key] 35 | } 36 | }) 37 | 38 | const listeners = {} 39 | listenersKeys.forEach((key) => { 40 | if (typeof transition[key] === 'function') { 41 | listeners[key] = transition[key].bind(_parent) 42 | } 43 | }) 44 | // Add triggerScroll event on beforeEnter (fix #1376) 45 | const beforeEnter = listeners.beforeEnter 46 | listeners.beforeEnter = (el) => { 47 | // Ensure to trigger scroll event after calling scrollBehavior 48 | window.$nuxt.$nextTick(() => { 49 | window.$nuxt.$emit('triggerScroll') 50 | }) 51 | if (beforeEnter) return beforeEnter.call(_parent, el) 52 | } 53 | 54 | let routerView = [ 55 | h('router-view', data) 56 | ] 57 | if (props.keepAlive) { 58 | routerView = [ 59 | h('keep-alive', { props: props.keepAliveProps }, routerView) 60 | ] 61 | } 62 | return h('transition', { 63 | props: transitionProps, 64 | on: listeners 65 | }, routerView) 66 | } 67 | } 68 | 69 | const transitionsKeys = [ 70 | 'name', 71 | 'mode', 72 | 'appear', 73 | 'css', 74 | 'type', 75 | 'duration', 76 | 'enterClass', 77 | 'leaveClass', 78 | 'appearClass', 79 | 'enterActiveClass', 80 | 'enterActiveClass', 81 | 'leaveActiveClass', 82 | 'appearActiveClass', 83 | 'enterToClass', 84 | 'leaveToClass', 85 | 'appearToClass' 86 | ] 87 | 88 | const listenersKeys = [ 89 | 'beforeEnter', 90 | 'enter', 91 | 'afterEnter', 92 | 'enterCancelled', 93 | 'beforeLeave', 94 | 'leave', 95 | 'afterLeave', 96 | 'leaveCancelled', 97 | 'beforeAppear', 98 | 'appear', 99 | 'afterAppear', 100 | 'appearCancelled' 101 | ] 102 | -------------------------------------------------------------------------------- /.nuxt/components/nuxt-error.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 50 | 51 | 96 | -------------------------------------------------------------------------------- /.nuxt/components/nuxt-link.client.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | const requestIdleCallback = window.requestIdleCallback || 4 | function (cb) { 5 | const start = Date.now() 6 | return setTimeout(function () { 7 | cb({ 8 | didTimeout: false, 9 | timeRemaining: function () { 10 | return Math.max(0, 50 - (Date.now() - start)) 11 | } 12 | }) 13 | }, 1) 14 | } 15 | const observer = window.IntersectionObserver && new window.IntersectionObserver((entries) => { 16 | entries.forEach(({ intersectionRatio, target: link }) => { 17 | if (intersectionRatio <= 0) { 18 | return 19 | } 20 | link.__prefetch() 21 | }) 22 | }) 23 | 24 | // @vue/component 25 | export default { 26 | name: 'NuxtLink', 27 | extends: Vue.component('RouterLink'), 28 | props: { 29 | noPrefetch: { 30 | type: Boolean, 31 | default: false 32 | } 33 | }, 34 | mounted() { 35 | if (!this.noPrefetch) { 36 | requestIdleCallback(this.observe, { timeout: 2e3 }) 37 | } 38 | }, 39 | beforeDestroy() { 40 | if (this.__observed) { 41 | observer.unobserve(this.$el) 42 | delete this.$el.__prefetch 43 | } 44 | }, 45 | methods: { 46 | observe() { 47 | // If no IntersectionObserver, avoid prefetching 48 | if (!observer) { 49 | return 50 | } 51 | // Add to observer 52 | if (this.shouldPrefetch()) { 53 | this.$el.__prefetch = this.prefetch.bind(this) 54 | observer.observe(this.$el) 55 | this.__observed = true 56 | } 57 | }, 58 | shouldPrefetch() { 59 | return this.getPrefetchComponents().length > 0 60 | }, 61 | canPrefetch() { 62 | const conn = navigator.connection 63 | const hasBadConnection = this.$nuxt.isOffline || (conn && ((conn.effectiveType || '').includes('2g') || conn.saveData)) 64 | 65 | return !hasBadConnection 66 | }, 67 | getPrefetchComponents() { 68 | const ref = this.$router.resolve(this.to, this.$route, this.append) 69 | const Components = ref.resolved.matched.map(r => r.components.default) 70 | 71 | return Components.filter(Component => typeof Component === 'function' && !Component.options && !Component.__prefetched) 72 | }, 73 | prefetch() { 74 | if (!this.canPrefetch()) { 75 | return 76 | } 77 | // Stop obersing this link (in case of internet connection changes) 78 | observer.unobserve(this.$el) 79 | const Components = this.getPrefetchComponents() 80 | 81 | for (const Component of Components) { 82 | const componentOrPromise = Component() 83 | if (componentOrPromise instanceof Promise) { 84 | componentOrPromise.catch(() => {}) 85 | } 86 | Component.__prefetched = true 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /.nuxt/components/nuxt-link.server.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | // @vue/component 4 | export default { 5 | name: 'NuxtLink', 6 | extends: Vue.component('RouterLink'), 7 | props: { 8 | noPrefetch: { 9 | type: Boolean, 10 | default: false 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.nuxt/components/nuxt-loading.vue: -------------------------------------------------------------------------------- 1 | 155 | 156 | 178 | -------------------------------------------------------------------------------- /.nuxt/components/nuxt.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { compile } from '../utils' 3 | 4 | import NuxtError from './nuxt-error.vue' 5 | 6 | import NuxtChild from './nuxt-child' 7 | 8 | // @vue/component 9 | export default { 10 | name: 'Nuxt', 11 | components: { 12 | NuxtChild, 13 | NuxtError 14 | }, 15 | props: { 16 | nuxtChildKey: { 17 | type: String, 18 | default: undefined 19 | }, 20 | keepAlive: Boolean, 21 | keepAliveProps: { 22 | type: Object, 23 | default: undefined 24 | }, 25 | name: { 26 | type: String, 27 | default: 'default' 28 | } 29 | }, 30 | computed: { 31 | routerViewKey() { 32 | // If nuxtChildKey prop is given or current route has children 33 | if (typeof this.nuxtChildKey !== 'undefined' || this.$route.matched.length > 1) { 34 | return this.nuxtChildKey || compile(this.$route.matched[0].path)(this.$route.params) 35 | } 36 | 37 | const [matchedRoute] = this.$route.matched 38 | 39 | if (!matchedRoute) { 40 | return this.$route.path 41 | } 42 | 43 | const Component = matchedRoute.components.default 44 | 45 | if (Component && Component.options) { 46 | const { options } = Component 47 | 48 | if (options.key) { 49 | return (typeof options.key === 'function' ? options.key(this.$route) : options.key) 50 | } 51 | } 52 | 53 | const strict = /\/$/.test(matchedRoute.path) 54 | return strict ? this.$route.path : this.$route.path.replace(/\/$/, '') 55 | } 56 | }, 57 | beforeCreate() { 58 | Vue.util.defineReactive(this, 'nuxt', this.$root.$options.nuxt) 59 | }, 60 | render(h) { 61 | // If there is some error 62 | if (this.nuxt.err) { 63 | return h('NuxtError', { 64 | props: { 65 | error: this.nuxt.err 66 | } 67 | }) 68 | } 69 | // Directly return nuxt child 70 | return h('NuxtChild', { 71 | key: this.routerViewKey, 72 | props: this.$props 73 | }) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /.nuxt/dist/client/08fd1945017a9e6f7c71.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[2],{224:function(n,t,e){"use strict";e.r(t);var l={},c=e(41),component=Object(c.a)(l,function(){var n=this.$createElement;return(this._self._c||n)("div",[this._v("\n create-nuxt-module default content\n")])},[],!1,null,null,null);t.default=component.exports}}]); -------------------------------------------------------------------------------- /.nuxt/dist/client/4bff0aa5c468a6e516c5.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[0],{134:function(t,e,n){t.exports=n(135)},135:function(t,e,n){"use strict";n.r(e),function(t){n(95),n(104),n(52);var e=n(43),r=(n(82),n(145),n(14)),o=(n(107),n(109),n(53),n(29),n(68),n(86),n(112),n(149),n(161),n(163),n(1)),c=n(131),f=n(93),l=n(2),h=n(32),d=n(76);o.a.component(d.a.name,d.a),o.a.component("NLink",d.a),t.fetch||(t.fetch=c.a);var m,v,x=[],y=window.__NUXT__||{};Object.assign(o.a.config,{silent:!0,performance:!1});var w=o.a.config.errorHandler||console.error;function _(t,e,n){var r=function(component){var t=function(component,t){if(!component||!component.options||!component.options[t])return{};var option=component.options[t];if("function"==typeof option){for(var e=arguments.length,n=new Array(e>2?e-2:0),r=2;r1&&void 0!==arguments[1]&&arguments[1];return Array.prototype.concat.apply([],t.matched.map(function(t,n){return Object.keys(t.components).map(function(r){return e&&e.push(n),t.components[r]})}))}function _(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return Array.prototype.concat.apply([],t.matched.map(function(t,n){return Object.keys(t.instances).map(function(r){return e&&e.push(n),t.instances[r]})}))}function O(t,e){return Array.prototype.concat.apply([],t.matched.map(function(t,n){return Object.keys(t.components).reduce(function(r,o){return t.components[o]?r.push(e(t.components[o],t.instances[o],t,o,n)):delete t.components[o],r},[])}))}function C(t){return Promise.all(O(t,function(){var t=Object(c.a)(regeneratorRuntime.mark(function t(e,n,r,o){return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:if("function"!=typeof e||e.options){t.next=4;break}return t.next=3,e();case 3:e=t.sent;case 4:return r.components[o]=y(e),t.abrupt("return",r.components[o]);case 6:case"end":return t.stop()}},t)}));return function(e,n,r,o){return t.apply(this,arguments)}}()))}function j(t){return k.apply(this,arguments)}function k(){return(k=Object(c.a)(regeneratorRuntime.mark(function t(e){return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:if(e){t.next=2;break}return t.abrupt("return");case 2:return t.next=4,C(e);case 4:return t.abrupt("return",d({},e,{meta:w(e).map(function(t,n){return d({},t.options.meta,{},(e.matched[n]||{}).meta)})}));case 5:case"end":return t.stop()}},t)}))).apply(this,arguments)}function $(t,e){return E.apply(this,arguments)}function E(){return(E=Object(c.a)(regeneratorRuntime.mark(function t(e,n){var c,f,l,h;return regeneratorRuntime.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return e.context||(e.context={isStatic:!1,isDev:!1,isHMR:!1,app:e,payload:n.payload,error:n.error,base:"/",env:{}},n.req&&(e.context.req=n.req),n.res&&(e.context.res=n.res),n.ssrContext&&(e.context.ssrContext=n.ssrContext),e.context.redirect=function(t,path,n){if(t){e.context._redirected=!0;var r=Object(o.a)(path);if("number"==typeof t||"undefined"!==r&&"object"!==r||(n=path||{},path=t,r=Object(o.a)(path),t=302),"object"===r&&(path=e.router.resolve(path).route.fullPath),!/(^[.]{1,2}\/)|(^\/(?!\/))/.test(path))throw path=I(path,n),window.location.replace(path),new Error("ERR_REDIRECT");e.context.next({path:path,query:n,status:t})}},e.context.nuxtState=window.__NUXT__),t.next=3,Promise.all([j(n.route),j(n.from)]);case 3:c=t.sent,f=Object(r.a)(c,2),l=f[0],h=f[1],n.route&&(e.context.route=l),n.from&&(e.context.from=h),e.context.next=n.next,e.context._redirected=!1,e.context._errored=!1,e.context.isHMR=Boolean(n.isHMR),e.context.params=e.context.route.params||{},e.context.query=e.context.route.query||{};case 15:case"end":return t.stop()}},t)}))).apply(this,arguments)}function R(t,e){return!t.length||e._redirected||e._errored?Promise.resolve():P(t[0],e).then(function(){return R(t.slice(1),e)})}function P(t,e){var n;return(n=2===t.length?new Promise(function(n){t(e,function(t,data){t&&e.error(t),n(data=data||{})})}):t(e))&&(n instanceof Promise||"function"==typeof n.then)||(n=Promise.resolve(n)),n}function S(base,t){var path=decodeURI(window.location.pathname);return"hash"===t?window.location.hash.replace(/^#\//,""):(base&&0===path.indexOf(base)&&(path=path.slice(base.length)),(path||"/")+window.location.search+window.location.hash)}function T(t,e){return function(t){for(var e=new Array(t.length),i=0;i1)return this.nuxtChildKey||Object(d.b)(this.$route.matched[0].path)(this.$route.params);var t=Object(E.a)(this.$route.matched,1)[0];if(!t)return this.$route.path;var e=t.components.default;if(e&&e.options){var n=e.options;if(n.key)return"function"==typeof n.key?n.key(this.$route):n.key}return/\/$/.test(t.path)?this.$route.path:this.$route.path.replace(/\/$/,"")}},beforeCreate:function(){c.a.util.defineReactive(this,"nuxt",this.$root.$options.nuxt)},render:function(t){return this.nuxt.err?t("NuxtError",{props:{error:this.nuxt.err}}):t("NuxtChild",{key:this.routerViewKey,props:this.$props})}},P={name:"NuxtLoading",data:function(){return{percent:0,show:!1,canSucceed:!0,reversed:!1,skipTimerCount:0,rtl:!1,throttle:200,duration:5e3,continuous:!1}},computed:{left:function(){return!(!this.continuous&&!this.rtl)&&(this.rtl?this.reversed?"0px":"auto":this.reversed?"auto":"0px")}},beforeDestroy:function(){this.clear()},methods:{clear:function(){clearInterval(this._timer),clearTimeout(this._throttle),this._timer=null},start:function(){var t=this;return this.clear(),this.percent=0,this.reversed=!1,this.skipTimerCount=0,this.canSucceed=!0,this.throttle?this._throttle=setTimeout(function(){return t.startTimer()},this.throttle):this.startTimer(),this},set:function(t){return this.show=!0,this.canSucceed=!0,this.percent=Math.min(100,Math.max(0,Math.floor(t))),this},get:function(){return this.percent},increase:function(t){return this.percent=Math.min(100,Math.floor(this.percent+t)),this},decrease:function(t){return this.percent=Math.max(0,Math.floor(this.percent-t)),this},pause:function(){return clearInterval(this._timer),this},resume:function(){return this.startTimer(),this},finish:function(){return this.percent=this.reversed?0:100,this.hide(),this},hide:function(){var t=this;return this.clear(),setTimeout(function(){t.show=!1,t.$nextTick(function(){t.percent=0,t.reversed=!1})},500),this},fail:function(){return this.canSucceed=!1,this},startTimer:function(){var t=this;this.show||(this.show=!0),void 0===this._cut&&(this._cut=1e4/Math.floor(this.duration)),this._timer=setInterval(function(){t.skipTimerCount>0?t.skipTimerCount--:(t.reversed?t.decrease(t._cut):t.increase(t._cut),t.continuous&&(t.percent>=100?(t.skipTimerCount=1,t.reversed=!t.reversed):t.percent<=0&&(t.skipTimerCount=1,t.reversed=!t.reversed)))},100)}},render:function(t){var e=t(!1);return this.show&&(e=t("div",{staticClass:"nuxt-progress",class:{"nuxt-progress-notransition":this.skipTimerCount>0,"nuxt-progress-failed":!this.canSucceed},style:{width:this.percent+"%",left:this.left}})),e}},S=(n(182),Object(k.a)(P,void 0,void 0,!1,null,null,null).exports),T={_default:Object(k.a)({},function(){var t=this.$createElement;return(this._self._c||t)("Nuxt")},[],!1,null,null,null).exports},N={head:{meta:[],link:[],style:[],script:[]},render:function(t,e){var n=t("NuxtLoading",{ref:"loading"}),r=t(this.layout||"nuxt"),o=t("div",{domProps:{id:"__layout"},key:this.layoutName},[r]),c=t("transition",{props:{name:"layout",mode:"out-in"},on:{beforeEnter:function(t){window.$nuxt.$nextTick(function(){window.$nuxt.$emit("triggerScroll")})}}},[o]);return t("div",{domProps:{id:"__nuxt"}},[n,c])},data:function(){return{isOnline:!0,layout:null,layoutName:""}},beforeCreate:function(){c.a.util.defineReactive(this,"nuxt",this.$options.nuxt)},created:function(){c.a.prototype.$nuxt=this,window.$nuxt=this,this.refreshOnlineStatus(),window.addEventListener("online",this.refreshOnlineStatus),window.addEventListener("offline",this.refreshOnlineStatus),this.error=this.nuxt.error},mounted:function(){this.$loading=this.$refs.loading},watch:{"nuxt.err":"errorChanged"},computed:{isOffline:function(){return!this.isOnline}},methods:{refreshOnlineStatus:function(){void 0===window.navigator.onLine?this.isOnline=!0:this.isOnline=window.navigator.onLine},errorChanged:function(){this.nuxt.err&&this.$loading&&(this.$loading.fail&&this.$loading.fail(),this.$loading.finish&&this.$loading.finish())},setLayout:function(t){return t&&T["_"+t]||(t="default"),this.layoutName=t,this.layout=T["_"+t],this.layout},loadLayout:function(t){return t&&T["_"+t]||(t="default"),Promise.resolve(T["_"+t])}},components:{NuxtLoading:S}},D=function(t){var e=n(184);e.initialize("",""),e.serverURL="https://parseapi.back4app.com/",c.a.prototype.$parse=e};function A(object,t){var e=Object.keys(object);return Object.getOwnPropertySymbols&&e.push.apply(e,Object.getOwnPropertySymbols(object)),t&&(e=e.filter(function(t){return Object.getOwnPropertyDescriptor(object,t).enumerable})),e}function L(t){for(var i=1;i0},canPrefetch:function(){var t=navigator.connection;return!(this.$nuxt.isOffline||t&&((t.effectiveType||"").includes("2g")||t.saveData))},getPrefetchComponents:function(){return this.$router.resolve(this.to,this.$route,this.append).resolved.matched.map(function(t){return t.components.default}).filter(function(t){return"function"==typeof t&&!t.options&&!t.__prefetched})},prefetch:function(){if(this.canPrefetch()){c.unobserve(this.$el);var t=this.getPrefetchComponents(),e=!0,n=!1,r=void 0;try{for(var o,f=t[Symbol.iterator]();!(e=(o=f.next()).done);e=!0){var l=o.value,h=l();h instanceof Promise&&h.catch(function(){}),l.__prefetched=!0}}catch(t){n=!0,r=t}finally{try{e||null==f.return||f.return()}finally{if(n)throw r}}}}}}},93:function(t,e,n){"use strict";e.a={}}},[[134,3,1,4]]]); -------------------------------------------------------------------------------- /.nuxt/dist/client/LICENSES: -------------------------------------------------------------------------------- 1 | /*! 2 | * Vue.js v2.6.10 3 | * (c) 2014-2019 Evan You 4 | * Released under the MIT License. 5 | */ 6 | 7 | /*! 8 | * vue-router v3.0.7 9 | * (c) 2019 Evan You 10 | * @license MIT 11 | */ 12 | 13 | /** 14 | * vue-meta v1.6.0 15 | * (c) 2019 Declan de Wet & Sébastien Chopin (@Atinux) 16 | * @license MIT 17 | */ 18 | 19 | /* 20 | object-assign 21 | (c) Sindre Sorhus 22 | @license MIT 23 | */ 24 | 25 | /*! 26 | * vue-no-ssr v1.1.1 27 | * (c) 2018-present egoist <0x142857@gmail.com> 28 | * Released under the MIT License. 29 | */ 30 | -------------------------------------------------------------------------------- /.nuxt/dist/client/e2ed95a5f585d36d08fb.js: -------------------------------------------------------------------------------- 1 | !function(e){function r(data){for(var r,n,f=data[0],l=data[1],d=data[2],i=0,h=[];i 2 | 3 | 4 | {{ HEAD }} 5 | 6 | 7 | {{ APP }} 8 | 9 | 10 | -------------------------------------------------------------------------------- /.nuxt/dist/server/index.ssr.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ HEAD }} 5 | 6 | 7 | {{ APP }} 8 | 9 | 10 | -------------------------------------------------------------------------------- /.nuxt/dist/server/server.js: -------------------------------------------------------------------------------- 1 | module.exports=function(t){var e={},r={0:0};function n(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.e=function(e){if(0!==r[e]){var n=require("./"+{1:"f1e952c8bf78d43839d8"}[e]+".js"),o=n.modules,c=n.ids;for(var l in o)t[l]=o[l];for(var i=0;i"+style.css+""}return e}r.r(e),r.d(e,"default",function(){return n})},function(t,e){t.exports=require("querystring")},function(t,e){t.exports=require("node-fetch")},function(t,e){t.exports=require("vue-meta")},function(t,e){t.exports=require("vue-no-ssr")},function(t,e,r){t.exports=r(17)},function(t,e,r){"use strict";r.r(e);var n=r(2),o=r.n(n);for(var c in n)"default"!==c&&function(t){r.d(e,t,function(){return n[t]})}(c);e.default=o.a},function(t,e,r){(t.exports=r(5)(!1)).push([t.i,".__nuxt-error-page{padding:1rem;background:#f7f8fb;color:#47494e;text-align:center;display:flex;justify-content:center;align-items:center;flex-direction:column;font-family:sans-serif;font-weight:100!important;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-webkit-font-smoothing:antialiased;position:absolute;top:0;left:0;right:0;bottom:0}.__nuxt-error-page .error{max-width:450px}.__nuxt-error-page .title{font-size:1.5rem;margin-top:15px;color:#47494e;margin-bottom:8px}.__nuxt-error-page .description{color:#7f828b;line-height:21px;margin-bottom:10px}.__nuxt-error-page a{color:#7f828b!important;text-decoration:none}.__nuxt-error-page .logo{position:fixed;left:12px;bottom:12px}",""])},function(t,e,r){"use strict";r.r(e);var n=r(3),o=r.n(n);for(var c in n)"default"!==c&&function(t){r.d(e,t,function(){return n[t]})}(c);e.default=o.a},function(t,e,r){(t.exports=r(5)(!1)).push([t.i,".nuxt-progress{position:fixed;top:0;left:0;right:0;height:2px;width:0;opacity:1;transition:width .1s,opacity .4s;background-color:#000;z-index:999999}.nuxt-progress.nuxt-progress-notransition{transition:none}.nuxt-progress-failed{background-color:red}",""])},function(t,e){t.exports=require("parse")},function(t,e,r){"use strict";r.r(e);var n=r(7),o=r(0),c=r.n(o),l=r(8),d=r.n(l);var f={};function h(t){return t.options&&t._Ctor===t?t:(t.options?(t._Ctor=t,t.extendOptions=t.options):(t=c.a.extend(t))._Ctor=t,!t.options.name&&t.options.__file&&(t.options.name=t.options.__file),t)}function m(t,e=!1){return Array.prototype.concat.apply([],t.matched.map((t,r)=>Object.keys(t.components).map(n=>(e&&e.push(r),t.components[n]))))}function x(t){return Promise.all(function(t,e){return Array.prototype.concat.apply([],t.matched.map((t,r)=>Object.keys(t.components).reduce((n,o)=>(t.components[o]?n.push(e(t.components[o],t.instances[o],t,o,r)):delete t.components[o],n),[])))}(t,async(t,e,r,n)=>("function"!=typeof t||t.options||(t=await t()),r.components[n]=h(t),r.components[n])))}async function y(t){if(t)return await x(t),{...t,meta:m(t).map((e,r)=>({...e.options.meta,...(t.matched[r]||{}).meta}))}}async function v(t,e){t.context||(t.context={isStatic:!1,isDev:!1,isHMR:!1,app:t,payload:e.payload,error:e.error,base:"/",env:{}},e.req&&(t.context.req=e.req),e.res&&(t.context.res=e.res),e.ssrContext&&(t.context.ssrContext=e.ssrContext),t.context.redirect=(e,path,r)=>{if(!e)return;t.context._redirected=!0;let n=typeof path;"number"==typeof e||"undefined"!==n&&"object"!==n||(r=path||{},n=typeof(path=e),e=302),"object"===n&&(path=t.router.resolve(path).route.fullPath),/(^[.]{1,2}\/)|(^\/(?!\/))/.test(path)?t.context.next({path:path,query:r,status:e}):(path=function(t,e){let r;const n=t.indexOf("://");-1!==n?(r=t.substring(0,n),t=t.substring(n+3)):t.startsWith("//")&&(t=t.substring(2));let o,c=t.split("/"),l=(r?r+"://":"//")+c.shift(),path=c.filter(Boolean).join("/");2===(c=path.split("#")).length&&([path,o]=c);l+=path?"/"+path:"",e&&"{}"!==JSON.stringify(e)&&(l+=(2===t.split("?").length?"&":"?")+function(t){return Object.keys(t).sort().map(e=>{const r=t[e];return null==r?"":Array.isArray(r)?r.slice().map(t=>[e,"=",t].join("")).join("&"):e+"="+r}).filter(Boolean).join("&")}(e));return l+=o?"#"+o:""}(path,r),t.context.next({path:path,status:e}))},t.context.beforeNuxtRender=t=>e.beforeRenderFns.push(t));const[r,n]=await Promise.all([y(e.route),y(e.from)]);e.route&&(t.context.route=r),e.from&&(t.context.from=n),t.context.next=e.next,t.context._redirected=!1,t.context._errored=!1,t.context.isHMR=Boolean(e.isHMR),t.context.params=t.context.route.params||{},t.context.query=t.context.route.query||{}}function _(t,e){return!t.length||e._redirected||e._errored?Promise.resolve():w(t[0],e).then(()=>_(t.slice(1),e))}function w(t,e){let r;return(r=2===t.length?new Promise(r=>{t(e,function(t,data){t&&e.error(t),r(data=data||{})})}):t(e))&&(r instanceof Promise||"function"==typeof r.then)||(r=Promise.resolve(r)),r}function C(t,e){return function(t){const e=new Array(t.length);for(let i=0;i"%"+t.charCodeAt(0).toString(16).toUpperCase()):c(n),!e[i].test(o))throw new TypeError('Expected "'+r.name+'" to match "'+r.pattern+'", but received "'+o+'"');path+=r.prefix+o}}return path}}(function(t,e){const r=[];let n=0,o=0,path="";const c=e&&e.delimiter||"/";let l;for(;null!=(l=$.exec(t));){const e=l[0],d=l[1],f=l.index;if(path+=t.slice(o,f),o=f+e.length,d){path+=d[1];continue}const h=t[o],m=l[2],x=l[3],y=l[4],v=l[5],_=l[6],w=l[7];path&&(r.push(path),path="");const C=null!=m&&null!=h&&h!==m,$="+"===_||"*"===_,k="?"===_||"*"===_,T=l[2]||c,pattern=y||v;r.push({name:x||n++,prefix:m||"",delimiter:T,optional:k,repeat:$,partial:C,asterisk:Boolean(w),pattern:pattern?j(pattern):w?".*":"[^"+S(T)+"]+?"})}o"%"+t.charCodeAt(0).toString(16).toUpperCase())}function S(t){return t.replace(/([.+*?=^!:${}()[\]|\/\\])/g,"\\$1")}function j(t){return t.replace(/([=!:$\/()])/g,"\\$1")}var T=r(9),E=r.n(T),O=r(4),N=r.n(O);const R=()=>(function(t){return t.then(t=>t.default||t)})(r.e(1).then(r.bind(null,18)));c.a.use(N.a);const P=function(t,e,r){let n=!1;return t.matched.length<2&&t.matched.every(t=>!1!==t.components.default.options.scrollToTop)?n={x:0,y:0}:t.matched.some(t=>t.components.default.options.scrollToTop)&&(n={x:0,y:0}),r&&(n=r),new Promise(e=>{window.$nuxt.$once("triggerScroll",()=>{if(t.hash){let e=t.hash;void 0!==window.CSS&&void 0!==window.CSS.escape&&(e="#"+window.CSS.escape(e.substr(1)));try{document.querySelector(e)&&(n={selector:e})}catch(t){console.warn("Failed to save scroll position. Please add CSS.escape() polyfill (https://github.com/mathiasbynens/CSS.escape).")}}e(n)})})};var A=r(10),M={...r.n(A).a,name:"NoSsr"},L={name:"NuxtChild",functional:!0,props:{nuxtChildKey:{type:String,default:""},keepAlive:Boolean,keepAliveProps:{type:Object,default:void 0}},render(t,{parent:e,data:data,props:r}){data.nuxtChild=!0;const n=e,o=e.$nuxt.nuxt.transitions,c=e.$nuxt.nuxt.defaultTransition;let l=0;for(;e;)e.$vnode&&e.$vnode.data.nuxtChild&&l++,e=e.$parent;data.nuxtChildDepth=l;const d=o[l]||c,f={};U.forEach(t=>{void 0!==d[t]&&(f[t]=d[t])});const h={};D.forEach(t=>{"function"==typeof d[t]&&(h[t]=d[t].bind(n))});const m=h.beforeEnter;h.beforeEnter=t=>{if(window.$nuxt.$nextTick(()=>{window.$nuxt.$emit("triggerScroll")}),m)return m.call(n,t)};let x=[t("router-view",data)];return r.keepAlive&&(x=[t("keep-alive",{props:r.keepAliveProps},x)]),t("transition",{props:f,on:h},x)}};const U=["name","mode","appear","css","type","duration","enterClass","leaveClass","appearClass","enterActiveClass","enterActiveClass","leaveActiveClass","appearActiveClass","enterToClass","leaveToClass","appearToClass"],D=["beforeEnter","enter","afterEnter","enterCancelled","beforeLeave","leave","afterLeave","leaveCancelled","beforeAppear","appear","afterAppear","appearCancelled"];var B={name:"NuxtError",props:{error:{type:Object,default:null}},head(){return{title:this.message,meta:[{name:"viewport",content:"width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"}]}},computed:{statusCode(){return this.error&&this.error.statusCode||500},message(){return this.error.message||"Error"}}},I=r(1);var z=Object(I.a)(B,function(){var t=this,e=t.$createElement,r=t._self._c||e;return r("div",{staticClass:"__nuxt-error-page"},[t._ssrNode('
',"
",[t._ssrNode('
'+t._ssrEscape(t._s(t.message))+"
"),404===t.statusCode?t._ssrNode('

',"

",[r("NuxtLink",{staticClass:"error-link",attrs:{to:"/"}},[t._v("Back to the home page")])],1):t._e(),t._ssrNode(' ')],2)])},[],!1,function(t){var e=r(12);e.__inject__&&e.__inject__(t)},null,"1f507778").exports,F={name:"Nuxt",components:{NuxtChild:L,NuxtError:z},props:{nuxtChildKey:{type:String,default:void 0},keepAlive:Boolean,keepAliveProps:{type:Object,default:void 0},name:{type:String,default:"default"}},computed:{routerViewKey(){if(void 0!==this.nuxtChildKey||this.$route.matched.length>1)return this.nuxtChildKey||C(this.$route.matched[0].path)(this.$route.params);const[t]=this.$route.matched;if(!t)return this.$route.path;const e=t.components.default;if(e&&e.options){const{options:t}=e;if(t.key)return"function"==typeof t.key?t.key(this.$route):t.key}return/\/$/.test(t.path)?this.$route.path:this.$route.path.replace(/\/$/,"")}},beforeCreate(){c.a.util.defineReactive(this,"nuxt",this.$root.$options.nuxt)},render(t){return this.nuxt.err?t("NuxtError",{props:{error:this.nuxt.err}}):t("NuxtChild",{key:this.routerViewKey,props:this.$props})}},K={name:"NuxtLoading",data:()=>({percent:0,show:!1,canSucceed:!0,reversed:!1,skipTimerCount:0,rtl:!1,throttle:200,duration:5e3,continuous:!1}),computed:{left(){return!(!this.continuous&&!this.rtl)&&(this.rtl?this.reversed?"0px":"auto":this.reversed?"auto":"0px")}},beforeDestroy(){this.clear()},methods:{clear(){clearInterval(this._timer),clearTimeout(this._throttle),this._timer=null},start(){return this.clear(),this.percent=0,this.reversed=!1,this.skipTimerCount=0,this.canSucceed=!0,this.throttle?this._throttle=setTimeout(()=>this.startTimer(),this.throttle):this.startTimer(),this},set(t){return this.show=!0,this.canSucceed=!0,this.percent=Math.min(100,Math.max(0,Math.floor(t))),this},get(){return this.percent},increase(t){return this.percent=Math.min(100,Math.floor(this.percent+t)),this},decrease(t){return this.percent=Math.max(0,Math.floor(this.percent-t)),this},pause(){return clearInterval(this._timer),this},resume(){return this.startTimer(),this},finish(){return this.percent=this.reversed?0:100,this.hide(),this},hide(){return this.clear(),setTimeout(()=>{this.show=!1,this.$nextTick(()=>{this.percent=0,this.reversed=!1})},500),this},fail(){return this.canSucceed=!1,this},startTimer(){this.show||(this.show=!0),void 0===this._cut&&(this._cut=1e4/Math.floor(this.duration)),this._timer=setInterval(()=>{this.skipTimerCount>0?this.skipTimerCount--:(this.reversed?this.decrease(this._cut):this.increase(this._cut),this.continuous&&(this.percent>=100?(this.skipTimerCount=1,this.reversed=!this.reversed):this.percent<=0&&(this.skipTimerCount=1,this.reversed=!this.reversed)))},100)}},render(t){let e=t(!1);return this.show&&(e=t("div",{staticClass:"nuxt-progress",class:{"nuxt-progress-notransition":this.skipTimerCount>0,"nuxt-progress-failed":!this.canSucceed},style:{width:this.percent+"%",left:this.left}})),e}};var V=Object(I.a)(K,void 0,void 0,!1,function(t){var e=r(14);e.__inject__&&e.__inject__(t)},null,"a0627f10").exports;const J={_default:Object(I.a)({},function(){var t=this.$createElement;return(this._self._c||t)("Nuxt")},[],!1,null,null,"bf105130").exports};var H={head:{meta:[],link:[],style:[],script:[]},render(t,e){const r=t("NuxtLoading",{ref:"loading"}),n=t(this.layout||"nuxt"),o=t("div",{domProps:{id:"__layout"},key:this.layoutName},[n]),c=t("transition",{props:{name:"layout",mode:"out-in"},on:{beforeEnter(t){window.$nuxt.$nextTick(()=>{window.$nuxt.$emit("triggerScroll")})}}},[o]);return t("div",{domProps:{id:"__nuxt"}},[r,c])},data:()=>({isOnline:!0,layout:null,layoutName:""}),beforeCreate(){c.a.util.defineReactive(this,"nuxt",this.$options.nuxt)},created(){c.a.prototype.$nuxt=this,this.error=this.nuxt.error},mounted(){this.$loading=this.$refs.loading},watch:{"nuxt.err":"errorChanged"},computed:{isOffline(){return!this.isOnline}},methods:{refreshOnlineStatus(){0},errorChanged(){this.nuxt.err&&this.$loading&&(this.$loading.fail&&this.$loading.fail(),this.$loading.finish&&this.$loading.finish())},setLayout(t){return t&&J["_"+t]||(t="default"),this.layoutName=t,this.layout=J["_"+t],this.layout},loadLayout:t=>(t&&J["_"+t]||(t="default"),Promise.resolve(J["_"+t]))},components:{NuxtLoading:V}},X=t=>{let e=r(16);e.initialize("",""),e.serverURL="https://parseapi.back4app.com/",c.a.prototype.$parse=e};c.a.component(M.name,M),c.a.component(L.name,L),c.a.component("NChild",L),c.a.component(F.name,F),c.a.use(E.a,{keyName:"head",attribute:"data-n-head",ssrAttribute:"data-n-head-ssr",tagIDKeyName:"hid"});const W={name:"page",mode:"out-in",appear:!1,appearClass:"appear",appearActiveClass:"appear-active",appearToClass:"appear-to"};async function G(t){const e=await new N.a({mode:"history",base:decodeURI("/"),linkActiveClass:"nuxt-link-active",linkExactActiveClass:"nuxt-link-exact-active",scrollBehavior:P,routes:[{path:"/",component:R,name:"index"}],fallback:!1}),r={router:e,nuxt:{defaultTransition:W,transitions:[W],setTransitions(t){return Array.isArray(t)||(t=[t]),t=t.map(t=>t=t?"string"==typeof t?Object.assign({},W,{name:t}):Object.assign({},W,t):W),this.$options.nuxt.transitions=t,t},err:null,dateErr:null,error(e){e=e||null,r.context._errored=Boolean(e),e=e?function(t){let e;if(t.message||"string"==typeof t)e=t.message||t;else try{e=JSON.stringify(t,null,2)}catch(r){e=`[${t.constructor.name}]`}return{...t,message:e,statusCode:t.statusCode||t.status||t.response&&t.response.status||500}}(e):null;const n=this.nuxt||this.$options.nuxt;return n.dateErr=Date.now(),n.err=e,t&&(t.nuxt.error=e),e}},...H},n=t?t.next:t=>r.router.push(t);let o;if(t)o=e.resolve(t.url).route;else{const path=function(base,t){let path=decodeURI(window.location.pathname);return"hash"===t?window.location.hash.replace(/^#\//,""):(base&&0===path.indexOf(base)&&(path=path.slice(base.length)),(path||"/")+window.location.search+window.location.hash)}(e.options.base);o=e.resolve(path).route}await v(r,{route:o,next:n,error:r.nuxt.error.bind(r),payload:t?t.payload:void 0,req:t?t.req:void 0,res:t?t.res:void 0,beforeRenderFns:t?t.beforeRenderFns:void 0,ssrContext:t});const l=function(t,e){if(!t)throw new Error("inject(key, value) has no key provided");if(void 0===e)throw new Error("inject(key, value) has no value provided");r[t="$"+t]=e;const n="__nuxt_"+t+"_installed__";c.a[n]||(c.a[n]=!0,c.a.use(()=>{c.a.prototype.hasOwnProperty(t)||Object.defineProperty(c.a.prototype,t,{get(){return this.$root.$options[t]}})}))};return"function"==typeof X&&await X(r.context,l),t&&t.url&&await new Promise((n,o)=>{e.push(t.url,n,()=>{const o=e.afterEach(async(e,c,l)=>{t.url=e.fullPath,r.context.route=await y(e),r.context.params=e.params||{},r.context.query=e.query||{},o(),n()})})}),{app:r,router:e}}var Q={name:"NuxtLink",extends:c.a.component("RouterLink"),props:{noPrefetch:{type:Boolean,default:!1}}};c.a.component(Q.name,Q),c.a.component("NLink",Q),global.fetch||(global.fetch=d.a);const Y=()=>new c.a({render:t=>t("div")}),Z=t=>e=>{if(t.redirected=e,!t.res)return void(t.nuxt.serverRendered=!1);e.query=Object(n.stringify)(e.query),e.path=e.path+(e.query?"?"+e.query:"");e.path.startsWith("http"),e.path!==t.url?(t.res.writeHead(e.status,{Location:e.path}),t.res.end()):t.redirected=!1};e.default=async t=>{t.redirected=!1,t.next=Z(t),t.beforeRenderFns=[],t.nuxt={layout:"default",data:[],error:null,serverRendered:!0};const{app:e,router:r}=await G(t),n=new c.a(e);t.meta=n.$meta(),t.asyncData={};const o=async()=>{await Promise.all(t.beforeRenderFns.map(e=>w(e,{Components:x,nuxtState:t.nuxt}))),t.rendered=()=>{}},l=async()=>{const r="function"==typeof z.layout?z.layout(e.context):z.layout;return t.nuxt.layout=r||"default",await n.loadLayout(r),n.setLayout(r),await o(),n},d=()=>(e.context.error({statusCode:404,path:t.url,message:"This page could not be found"}),l()),x=m(r.match(t.url));let y=[];if(y=y.map(t=>"function"==typeof t?t:("function"!=typeof f[t]&&e.context.error({statusCode:500,message:"Unknown middleware "+t}),f[t])),await _(y,e.context),t.redirected)return Y();if(t.nuxt.error)return l();let v=x.length?x[0].options.layout:z.layout;if("function"==typeof v&&(v=v(e.context)),await n.loadLayout(v),t.nuxt.error)return l();if(v=n.setLayout(v),t.nuxt.layout=n.layoutName,y=[],(v=h(v)).options.middleware&&(y=y.concat(v.options.middleware)),x.forEach(t=>{t.options.middleware&&(y=y.concat(t.options.middleware))}),y=y.map(t=>"function"==typeof t?t:("function"!=typeof f[t]&&e.context.error({statusCode:500,message:"Unknown middleware "+t}),f[t])),await _(y,e.context),t.redirected)return Y();if(t.nuxt.error)return l();let C=!0;try{for(const t of x)if("function"==typeof t.options.validate&&!(C=await t.options.validate(e.context)))break}catch(t){return e.context.error({statusCode:t.statusCode||"500",message:t.message}),l()}if(!C)return t._generate&&(t.nuxt.serverRendered=!1),d();if(!x.length)return d();const $=await Promise.all(x.map(r=>{const n=[];if(r.options.asyncData&&"function"==typeof r.options.asyncData){const o=w(r.options.asyncData,e.context);o.then(e=>(t.asyncData[r.cid]=e,function(t,e){if(!e&&t.options.__hasNuxtData)return;const r=t.options._originDataFn||t.options.data||function(){return{}};t.options._originDataFn=r,t.options.data=function(){const data=r.call(this);return this.$ssrContext&&(e=this.$ssrContext.asyncData[t.cid]),{...data,...e}},t.options.__hasNuxtData=!0,t._Ctor&&t._Ctor.options&&(t._Ctor.options.data=t.options.data)}(r),e)),n.push(o)}else n.push(null);return r.options.fetch?n.push(r.options.fetch(e.context)):n.push(null),Promise.all(n)}));return t.nuxt.data=$.map(t=>t[0]||{}),t.redirected?Y():t.nuxt.error?l():(await o(),n)}}]); 2 | //# sourceMappingURL=server.js.map -------------------------------------------------------------------------------- /.nuxt/dist/server/server.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"server.js","sources":["webpack:///webpack/bootstrap"],"sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// object to store loaded chunks\n \t// \"0\" means \"already loaded\"\n \tvar installedChunks = {\n \t\t0: 0\n \t};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n \t// This file contains only the entry chunk.\n \t// The chunk loading function for additional chunks\n \t__webpack_require__.e = function requireEnsure(chunkId) {\n \t\tvar promises = [];\n\n\n \t\t// require() chunk loading for javascript\n\n \t\t// \"0\" is the signal for \"already loaded\"\n \t\tif(installedChunks[chunkId] !== 0) {\n \t\t\tvar chunk = require(\"./\" + {\"1\":\"f1e952c8bf78d43839d8\"}[chunkId] + \".js\");\n \t\t\tvar moreModules = chunk.modules, chunkIds = chunk.ids;\n \t\t\tfor(var moduleId in moreModules) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t\tfor(var i = 0; i < chunkIds.length; i++)\n \t\t\t\tinstalledChunks[chunkIds[i]] = 0;\n \t\t}\n \t\treturn Promise.all(promises);\n \t};\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/_nuxt/\";\n\n \t// uncaught error handler for webpack runtime\n \t__webpack_require__.oe = function(err) {\n \t\tprocess.nextTick(function() {\n \t\t\tthrow err; // catch this error by using import().catch()\n \t\t});\n \t};\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 11);\n"],"mappings":"AACA","sourceRoot":""} -------------------------------------------------------------------------------- /.nuxt/dist/server/server.manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "entry": "server.js", 3 | "files": { 4 | "f1e952c8bf78d43839d8.js": "f1e952c8bf78d43839d8.js", 5 | "server.js": "server.js" 6 | }, 7 | "maps": { 8 | "f1e952c8bf78d43839d8.js": "f1e952c8bf78d43839d8.js.map", 9 | "server.js": "server.js.map" 10 | } 11 | } -------------------------------------------------------------------------------- /.nuxt/empty.js: -------------------------------------------------------------------------------- 1 | // This file is intentionally left empty for noop aliases 2 | -------------------------------------------------------------------------------- /.nuxt/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Meta from 'vue-meta' 3 | import { createRouter } from './router.js' 4 | import NoSsr from './components/no-ssr.js' 5 | import NuxtChild from './components/nuxt-child.js' 6 | import NuxtError from './components/nuxt-error.vue' 7 | import Nuxt from './components/nuxt.js' 8 | import App from './App.js' 9 | import { setContext, getLocation, getRouteData, normalizeError } from './utils' 10 | 11 | /* Plugins */ 12 | /* eslint-disable camelcase */ 13 | import nuxt_plugin_libmoduleplugin52b4b1c3_fe306f5c from 'nuxt_plugin_libmoduleplugin52b4b1c3_fe306f5c' // Source: ./lib.module.plugin.52b4b1c3.js (mode: 'all') 14 | 15 | /* eslint-enable camelcase */ 16 | 17 | // Component: 18 | Vue.component(NoSsr.name, NoSsr) 19 | 20 | // Component: 21 | Vue.component(NuxtChild.name, NuxtChild) 22 | Vue.component('NChild', NuxtChild) 23 | 24 | // Component NuxtLink is imported in server.js or client.js 25 | 26 | // Component: ` 27 | Vue.component(Nuxt.name, Nuxt) 28 | 29 | // vue-meta configuration 30 | Vue.use(Meta, { 31 | keyName: 'head', // the component option name that vue-meta looks for meta info on. 32 | attribute: 'data-n-head', // the attribute name vue-meta adds to the tags it observes 33 | ssrAttribute: 'data-n-head-ssr', // the attribute name that lets vue-meta know that meta info has already been server-rendered 34 | tagIDKeyName: 'hid' // the property name that vue-meta uses to determine whether to overwrite or append a tag 35 | }) 36 | 37 | const defaultTransition = {"name":"page","mode":"out-in","appear":false,"appearClass":"appear","appearActiveClass":"appear-active","appearToClass":"appear-to"}// eslint-disable-line 38 | 39 | async function createApp(ssrContext) { 40 | const router = await createRouter(ssrContext) 41 | 42 | // Create Root instance 43 | 44 | // here we inject the router and store to all child components, 45 | // making them available everywhere as `this.$router` and `this.$store`. 46 | const app = { 47 | router, 48 | 49 | nuxt: { 50 | defaultTransition, 51 | transitions: [ defaultTransition ], 52 | setTransitions(transitions) { 53 | if (!Array.isArray(transitions)) { 54 | transitions = [ transitions ] 55 | } 56 | transitions = transitions.map((transition) => { 57 | if (!transition) { 58 | transition = defaultTransition 59 | } else if (typeof transition === 'string') { 60 | transition = Object.assign({}, defaultTransition, { name: transition }) 61 | } else { 62 | transition = Object.assign({}, defaultTransition, transition) 63 | } 64 | return transition 65 | }) 66 | this.$options.nuxt.transitions = transitions 67 | return transitions 68 | }, 69 | err: null, 70 | dateErr: null, 71 | error(err) { 72 | err = err || null 73 | app.context._errored = Boolean(err) 74 | err = err ? normalizeError(err) : null 75 | const nuxt = this.nuxt || this.$options.nuxt 76 | nuxt.dateErr = Date.now() 77 | nuxt.err = err 78 | // Used in src/server.js 79 | if (ssrContext) ssrContext.nuxt.error = err 80 | return err 81 | } 82 | }, 83 | ...App 84 | } 85 | 86 | const next = ssrContext ? ssrContext.next : location => app.router.push(location) 87 | // Resolve route 88 | let route 89 | if (ssrContext) { 90 | route = router.resolve(ssrContext.url).route 91 | } else { 92 | const path = getLocation(router.options.base) 93 | route = router.resolve(path).route 94 | } 95 | 96 | // Set context to app.context 97 | await setContext(app, { 98 | route, 99 | next, 100 | error: app.nuxt.error.bind(app), 101 | 102 | payload: ssrContext ? ssrContext.payload : undefined, 103 | req: ssrContext ? ssrContext.req : undefined, 104 | res: ssrContext ? ssrContext.res : undefined, 105 | beforeRenderFns: ssrContext ? ssrContext.beforeRenderFns : undefined, 106 | ssrContext 107 | }) 108 | 109 | const inject = function (key, value) { 110 | if (!key) throw new Error('inject(key, value) has no key provided') 111 | if (typeof value === 'undefined') throw new Error('inject(key, value) has no value provided') 112 | key = '$' + key 113 | // Add into app 114 | app[key] = value 115 | 116 | // Check if plugin not already installed 117 | const installKey = '__nuxt_' + key + '_installed__' 118 | if (Vue[installKey]) return 119 | Vue[installKey] = true 120 | // Call Vue.use() to install the plugin into vm 121 | Vue.use(() => { 122 | if (!Vue.prototype.hasOwnProperty(key)) { 123 | Object.defineProperty(Vue.prototype, key, { 124 | get() { 125 | return this.$root.$options[key] 126 | } 127 | }) 128 | } 129 | }) 130 | } 131 | 132 | // Plugin execution 133 | /* eslint-disable camelcase */ 134 | 135 | if (typeof nuxt_plugin_libmoduleplugin52b4b1c3_fe306f5c === 'function') { 136 | await nuxt_plugin_libmoduleplugin52b4b1c3_fe306f5c(app.context, inject) 137 | } 138 | 139 | /* eslint-enable camelcase */ 140 | 141 | // If server-side, wait for async component to be resolved first 142 | if (process.server && ssrContext && ssrContext.url) { 143 | await new Promise((resolve, reject) => { 144 | router.push(ssrContext.url, resolve, () => { 145 | // navigated to a different route in router guard 146 | const unregister = router.afterEach(async (to, from, next) => { 147 | ssrContext.url = to.fullPath 148 | app.context.route = await getRouteData(to) 149 | app.context.params = to.params || {} 150 | app.context.query = to.query || {} 151 | unregister() 152 | resolve() 153 | }) 154 | }) 155 | }) 156 | } 157 | 158 | return { 159 | app, 160 | 161 | router 162 | } 163 | } 164 | 165 | export { createApp, NuxtError } 166 | -------------------------------------------------------------------------------- /.nuxt/layouts/default.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /.nuxt/lib.module.plugin.52b4b1c3.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | export default context => { 4 | let Parse = require('parse'); 5 | 6 | Parse.initialize('', ''); 7 | 8 | Parse.serverURL = 'https://parseapi.back4app.com/' 9 | 10 | Vue.prototype.$parse = Parse; 11 | } 12 | -------------------------------------------------------------------------------- /.nuxt/loading.html: -------------------------------------------------------------------------------- 1 | 97 | 98 | 104 | 105 |
Loading...
106 | -------------------------------------------------------------------------------- /.nuxt/middleware.js: -------------------------------------------------------------------------------- 1 | const middleware = {} 2 | 3 | export default middleware 4 | -------------------------------------------------------------------------------- /.nuxt/router.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import { interopDefault } from './utils'// eslint-disable-line no-unused-vars 4 | 5 | const _160032f3 = () => interopDefault(import('../test/fixture/pages/index.vue' /* webpackChunkName: "pages/index" */)) 6 | 7 | Vue.use(Router) 8 | 9 | if (process.client) { 10 | if ('scrollRestoration' in window.history) { 11 | window.history.scrollRestoration = 'manual' 12 | 13 | // reset scrollRestoration to auto when leaving page, allowing page reload 14 | // and back-navigation from other pages to use the browser to restore the 15 | // scrolling position. 16 | window.addEventListener('beforeunload', () => { 17 | window.history.scrollRestoration = 'auto' 18 | }) 19 | 20 | // Setting scrollRestoration to manual again when returning to this page. 21 | window.addEventListener('load', () => { 22 | window.history.scrollRestoration = 'manual' 23 | }) 24 | } 25 | } 26 | const scrollBehavior = function (to, from, savedPosition) { 27 | // if the returned position is falsy or an empty object, 28 | // will retain current scroll position. 29 | let position = false 30 | 31 | // if no children detected and scrollToTop is not explicitly disabled 32 | if ( 33 | to.matched.length < 2 && 34 | to.matched.every(r => r.components.default.options.scrollToTop !== false) 35 | ) { 36 | // scroll to the top of the page 37 | position = { x: 0, y: 0 } 38 | } else if (to.matched.some(r => r.components.default.options.scrollToTop)) { 39 | // if one of the children has scrollToTop option set to true 40 | position = { x: 0, y: 0 } 41 | } 42 | 43 | // savedPosition is only available for popstate navigations (back button) 44 | if (savedPosition) { 45 | position = savedPosition 46 | } 47 | 48 | return new Promise((resolve) => { 49 | // wait for the out transition to complete (if necessary) 50 | window.$nuxt.$once('triggerScroll', () => { 51 | // coords will be used if no selector is provided, 52 | // or if the selector didn't match any element. 53 | if (to.hash) { 54 | let hash = to.hash 55 | // CSS.escape() is not supported with IE and Edge. 56 | if (typeof window.CSS !== 'undefined' && typeof window.CSS.escape !== 'undefined') { 57 | hash = '#' + window.CSS.escape(hash.substr(1)) 58 | } 59 | try { 60 | if (document.querySelector(hash)) { 61 | // scroll to anchor by returning the selector 62 | position = { selector: hash } 63 | } 64 | } catch (e) { 65 | console.warn('Failed to save scroll position. Please add CSS.escape() polyfill (https://github.com/mathiasbynens/CSS.escape).') 66 | } 67 | } 68 | resolve(position) 69 | }) 70 | }) 71 | } 72 | 73 | export function createRouter() { 74 | return new Router({ 75 | mode: 'history', 76 | base: decodeURI('/'), 77 | linkActiveClass: 'nuxt-link-active', 78 | linkExactActiveClass: 'nuxt-link-exact-active', 79 | scrollBehavior, 80 | /* eslint-disable quotes, object-curly-spacing, key-spacing */ 81 | routes: [{ 82 | path: "/", 83 | component: _160032f3, 84 | name: "index" 85 | }], 86 | /* eslint-enable quotes, object-curly-spacing, key-spacing */ 87 | 88 | fallback: false 89 | }) 90 | } 91 | -------------------------------------------------------------------------------- /.nuxt/server.js: -------------------------------------------------------------------------------- 1 | import { stringify } from 'querystring' 2 | import Vue from 'vue' 3 | import fetch from 'node-fetch' 4 | import middleware from './middleware.js' 5 | import { applyAsyncData, getMatchedComponents, middlewareSeries, promisify, urlJoin, sanitizeComponent } from './utils.js' 6 | import { createApp, NuxtError } from './index.js' 7 | import NuxtLink from './components/nuxt-link.server.js' // should be included after ./index.js 8 | 9 | // Component: 10 | Vue.component(NuxtLink.name, NuxtLink) 11 | Vue.component('NLink', NuxtLink) 12 | 13 | if (!global.fetch) { global.fetch = fetch } 14 | 15 | const noopApp = () => new Vue({ render: h => h('div') }) 16 | 17 | const createNext = ssrContext => (opts) => { 18 | ssrContext.redirected = opts 19 | // If nuxt generate 20 | if (!ssrContext.res) { 21 | ssrContext.nuxt.serverRendered = false 22 | return 23 | } 24 | opts.query = stringify(opts.query) 25 | opts.path = opts.path + (opts.query ? '?' + opts.query : '') 26 | const routerBase = '/' 27 | if (!opts.path.startsWith('http') && (routerBase !== '/' && !opts.path.startsWith(routerBase))) { 28 | opts.path = urlJoin(routerBase, opts.path) 29 | } 30 | // Avoid loop redirect 31 | if (opts.path === ssrContext.url) { 32 | ssrContext.redirected = false 33 | return 34 | } 35 | ssrContext.res.writeHead(opts.status, { 36 | 'Location': opts.path 37 | }) 38 | ssrContext.res.end() 39 | } 40 | 41 | // This exported function will be called by `bundleRenderer`. 42 | // This is where we perform data-prefetching to determine the 43 | // state of our application before actually rendering it. 44 | // Since data fetching is async, this function is expected to 45 | // return a Promise that resolves to the app instance. 46 | export default async (ssrContext) => { 47 | // Create ssrContext.next for simulate next() of beforeEach() when wanted to redirect 48 | ssrContext.redirected = false 49 | ssrContext.next = createNext(ssrContext) 50 | // Used for beforeNuxtRender({ Components, nuxtState }) 51 | ssrContext.beforeRenderFns = [] 52 | // Nuxt object (window{{globals.context}}, defaults to window.__NUXT__) 53 | ssrContext.nuxt = { layout: 'default', data: [], error: null, serverRendered: true } 54 | // Create the app definition and the instance (created for each request) 55 | const { app, router } = await createApp(ssrContext) 56 | const _app = new Vue(app) 57 | 58 | // Add meta infos (used in renderer.js) 59 | ssrContext.meta = _app.$meta() 60 | // Keep asyncData for each matched component in ssrContext (used in app/utils.js via this.$ssrContext) 61 | ssrContext.asyncData = {} 62 | 63 | const beforeRender = async () => { 64 | // Call beforeNuxtRender() methods 65 | await Promise.all(ssrContext.beforeRenderFns.map(fn => promisify(fn, { Components, nuxtState: ssrContext.nuxt }))) 66 | ssrContext.rendered = () => { 67 | } 68 | } 69 | const renderErrorPage = async () => { 70 | // Load layout for error page 71 | const errLayout = (typeof NuxtError.layout === 'function' ? NuxtError.layout(app.context) : NuxtError.layout) 72 | ssrContext.nuxt.layout = errLayout || 'default' 73 | await _app.loadLayout(errLayout) 74 | _app.setLayout(errLayout) 75 | await beforeRender() 76 | return _app 77 | } 78 | const render404Page = () => { 79 | app.context.error({ statusCode: 404, path: ssrContext.url, message: `This page could not be found` }) 80 | return renderErrorPage() 81 | } 82 | 83 | // Components are already resolved by setContext -> getRouteData (app/utils.js) 84 | const Components = getMatchedComponents(router.match(ssrContext.url)) 85 | 86 | /* 87 | ** Call global middleware (nuxt.config.js) 88 | */ 89 | let midd = []// eslint-disable-line 90 | midd = midd.map((name) => { 91 | if (typeof name === 'function') return name 92 | if (typeof middleware[name] !== 'function') { 93 | app.context.error({ statusCode: 500, message: 'Unknown middleware ' + name }) 94 | } 95 | return middleware[name] 96 | }) 97 | await middlewareSeries(midd, app.context) 98 | // ...If there is a redirect or an error, stop the process 99 | if (ssrContext.redirected) return noopApp() 100 | if (ssrContext.nuxt.error) return renderErrorPage() 101 | 102 | /* 103 | ** Set layout 104 | */ 105 | let layout = Components.length ? Components[0].options.layout : NuxtError.layout 106 | if (typeof layout === 'function') layout = layout(app.context) 107 | await _app.loadLayout(layout) 108 | if (ssrContext.nuxt.error) return renderErrorPage() 109 | layout = _app.setLayout(layout) 110 | ssrContext.nuxt.layout = _app.layoutName 111 | 112 | /* 113 | ** Call middleware (layout + pages) 114 | */ 115 | midd = [] 116 | layout = sanitizeComponent(layout) 117 | if (layout.options.middleware) midd = midd.concat(layout.options.middleware) 118 | Components.forEach((Component) => { 119 | if (Component.options.middleware) { 120 | midd = midd.concat(Component.options.middleware) 121 | } 122 | }) 123 | midd = midd.map((name) => { 124 | if (typeof name === 'function') return name 125 | if (typeof middleware[name] !== 'function') { 126 | app.context.error({ statusCode: 500, message: 'Unknown middleware ' + name }) 127 | } 128 | return middleware[name] 129 | }) 130 | await middlewareSeries(midd, app.context) 131 | // ...If there is a redirect or an error, stop the process 132 | if (ssrContext.redirected) return noopApp() 133 | if (ssrContext.nuxt.error) return renderErrorPage() 134 | 135 | /* 136 | ** Call .validate() 137 | */ 138 | let isValid = true 139 | try { 140 | for (const Component of Components) { 141 | if (typeof Component.options.validate !== 'function') { 142 | continue 143 | } 144 | 145 | isValid = await Component.options.validate(app.context) 146 | 147 | if (!isValid) { 148 | break 149 | } 150 | } 151 | } catch (validationError) { 152 | // ...If .validate() threw an error 153 | app.context.error({ 154 | statusCode: validationError.statusCode || '500', 155 | message: validationError.message 156 | }) 157 | return renderErrorPage() 158 | } 159 | 160 | // ...If .validate() returned false 161 | if (!isValid) { 162 | // Don't server-render the page in generate mode 163 | if (ssrContext._generate) ssrContext.nuxt.serverRendered = false 164 | // Render a 404 error page 165 | return render404Page() 166 | } 167 | 168 | // If no Components found, returns 404 169 | if (!Components.length) return render404Page() 170 | 171 | // Call asyncData & fetch hooks on components matched by the route. 172 | const asyncDatas = await Promise.all(Components.map((Component) => { 173 | const promises = [] 174 | 175 | // Call asyncData(context) 176 | if (Component.options.asyncData && typeof Component.options.asyncData === 'function') { 177 | const promise = promisify(Component.options.asyncData, app.context) 178 | promise.then((asyncDataResult) => { 179 | ssrContext.asyncData[Component.cid] = asyncDataResult 180 | applyAsyncData(Component) 181 | return asyncDataResult 182 | }) 183 | promises.push(promise) 184 | } else { 185 | promises.push(null) 186 | } 187 | 188 | // Call fetch(context) 189 | if (Component.options.fetch) { 190 | promises.push(Component.options.fetch(app.context)) 191 | } else { 192 | promises.push(null) 193 | } 194 | 195 | return Promise.all(promises) 196 | })) 197 | 198 | // datas are the first row of each 199 | ssrContext.nuxt.data = asyncDatas.map(r => r[0] || {}) 200 | 201 | // ...If there is a redirect or an error, stop the process 202 | if (ssrContext.redirected) return noopApp() 203 | if (ssrContext.nuxt.error) return renderErrorPage() 204 | 205 | // Call beforeNuxtRender methods & add store state 206 | await beforeRender() 207 | 208 | return _app 209 | } 210 | -------------------------------------------------------------------------------- /.nuxt/utils.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | // window.{{globals.loadedCallback}} hook 4 | // Useful for jsdom testing or plugins (https://github.com/tmpvar/jsdom#dealing-with-asynchronous-script-loading) 5 | if (process.client) { 6 | window.onNuxtReadyCbs = [] 7 | window.onNuxtReady = (cb) => { 8 | window.onNuxtReadyCbs.push(cb) 9 | } 10 | } 11 | 12 | export function empty() {} 13 | 14 | export function globalHandleError(error) { 15 | if (Vue.config.errorHandler) { 16 | Vue.config.errorHandler(error) 17 | } 18 | } 19 | 20 | export function interopDefault(promise) { 21 | return promise.then(m => m.default || m) 22 | } 23 | 24 | export function applyAsyncData(Component, asyncData) { 25 | if ( 26 | // For SSR, we once all this function without second param to just apply asyncData 27 | // Prevent doing this for each SSR request 28 | !asyncData && Component.options.__hasNuxtData 29 | ) { 30 | return 31 | } 32 | 33 | const ComponentData = Component.options._originDataFn || Component.options.data || function () { return {} } 34 | Component.options._originDataFn = ComponentData 35 | 36 | Component.options.data = function () { 37 | const data = ComponentData.call(this) 38 | if (this.$ssrContext) { 39 | asyncData = this.$ssrContext.asyncData[Component.cid] 40 | } 41 | return { ...data, ...asyncData } 42 | } 43 | 44 | Component.options.__hasNuxtData = true 45 | 46 | if (Component._Ctor && Component._Ctor.options) { 47 | Component._Ctor.options.data = Component.options.data 48 | } 49 | } 50 | 51 | export function sanitizeComponent(Component) { 52 | // If Component already sanitized 53 | if (Component.options && Component._Ctor === Component) { 54 | return Component 55 | } 56 | if (!Component.options) { 57 | Component = Vue.extend(Component) // fix issue #6 58 | Component._Ctor = Component 59 | } else { 60 | Component._Ctor = Component 61 | Component.extendOptions = Component.options 62 | } 63 | // For debugging purpose 64 | if (!Component.options.name && Component.options.__file) { 65 | Component.options.name = Component.options.__file 66 | } 67 | return Component 68 | } 69 | 70 | export function getMatchedComponents(route, matches = false) { 71 | return Array.prototype.concat.apply([], route.matched.map((m, index) => { 72 | return Object.keys(m.components).map((key) => { 73 | matches && matches.push(index) 74 | return m.components[key] 75 | }) 76 | })) 77 | } 78 | 79 | export function getMatchedComponentsInstances(route, matches = false) { 80 | return Array.prototype.concat.apply([], route.matched.map((m, index) => { 81 | return Object.keys(m.instances).map((key) => { 82 | matches && matches.push(index) 83 | return m.instances[key] 84 | }) 85 | })) 86 | } 87 | 88 | export function flatMapComponents(route, fn) { 89 | return Array.prototype.concat.apply([], route.matched.map((m, index) => { 90 | return Object.keys(m.components).reduce((promises, key) => { 91 | if (m.components[key]) { 92 | promises.push(fn(m.components[key], m.instances[key], m, key, index)) 93 | } else { 94 | delete m.components[key] 95 | } 96 | return promises 97 | }, []) 98 | })) 99 | } 100 | 101 | export function resolveRouteComponents(route) { 102 | return Promise.all( 103 | flatMapComponents(route, async (Component, _, match, key) => { 104 | // If component is a function, resolve it 105 | if (typeof Component === 'function' && !Component.options) { 106 | Component = await Component() 107 | } 108 | match.components[key] = sanitizeComponent(Component) 109 | return match.components[key] 110 | }) 111 | ) 112 | } 113 | 114 | export async function getRouteData(route) { 115 | if (!route) { 116 | return 117 | } 118 | // Make sure the components are resolved (code-splitting) 119 | await resolveRouteComponents(route) 120 | // Send back a copy of route with meta based on Component definition 121 | return { 122 | ...route, 123 | meta: getMatchedComponents(route).map((Component, index) => { 124 | return { ...Component.options.meta, ...(route.matched[index] || {}).meta } 125 | }) 126 | } 127 | } 128 | 129 | export async function setContext(app, context) { 130 | // If context not defined, create it 131 | if (!app.context) { 132 | app.context = { 133 | isStatic: process.static, 134 | isDev: false, 135 | isHMR: false, 136 | app, 137 | 138 | payload: context.payload, 139 | error: context.error, 140 | base: '/', 141 | env: {}// eslint-disable-line 142 | } 143 | // Only set once 144 | if (context.req) { 145 | app.context.req = context.req 146 | } 147 | if (context.res) { 148 | app.context.res = context.res 149 | } 150 | if (context.ssrContext) { 151 | app.context.ssrContext = context.ssrContext 152 | } 153 | app.context.redirect = (status, path, query) => { 154 | if (!status) { 155 | return 156 | } 157 | app.context._redirected = true 158 | // if only 1 or 2 arguments: redirect('/') or redirect('/', { foo: 'bar' }) 159 | let pathType = typeof path 160 | if (typeof status !== 'number' && (pathType === 'undefined' || pathType === 'object')) { 161 | query = path || {} 162 | path = status 163 | pathType = typeof path 164 | status = 302 165 | } 166 | if (pathType === 'object') { 167 | path = app.router.resolve(path).route.fullPath 168 | } 169 | // "/absolute/route", "./relative/route" or "../relative/route" 170 | if (/(^[.]{1,2}\/)|(^\/(?!\/))/.test(path)) { 171 | app.context.next({ 172 | path, 173 | query, 174 | status 175 | }) 176 | } else { 177 | path = formatUrl(path, query) 178 | if (process.server) { 179 | app.context.next({ 180 | path, 181 | status 182 | }) 183 | } 184 | if (process.client) { 185 | // https://developer.mozilla.org/en-US/docs/Web/API/Location/replace 186 | window.location.replace(path) 187 | 188 | // Throw a redirect error 189 | throw new Error('ERR_REDIRECT') 190 | } 191 | } 192 | } 193 | if (process.server) { 194 | app.context.beforeNuxtRender = fn => context.beforeRenderFns.push(fn) 195 | } 196 | if (process.client) { 197 | app.context.nuxtState = window.__NUXT__ 198 | } 199 | } 200 | 201 | // Dynamic keys 202 | const [currentRouteData, fromRouteData] = await Promise.all([ 203 | getRouteData(context.route), 204 | getRouteData(context.from) 205 | ]) 206 | 207 | if (context.route) { 208 | app.context.route = currentRouteData 209 | } 210 | 211 | if (context.from) { 212 | app.context.from = fromRouteData 213 | } 214 | 215 | app.context.next = context.next 216 | app.context._redirected = false 217 | app.context._errored = false 218 | app.context.isHMR = Boolean(context.isHMR) 219 | app.context.params = app.context.route.params || {} 220 | app.context.query = app.context.route.query || {} 221 | } 222 | 223 | export function middlewareSeries(promises, appContext) { 224 | if (!promises.length || appContext._redirected || appContext._errored) { 225 | return Promise.resolve() 226 | } 227 | return promisify(promises[0], appContext) 228 | .then(() => { 229 | return middlewareSeries(promises.slice(1), appContext) 230 | }) 231 | } 232 | 233 | export function promisify(fn, context) { 234 | let promise 235 | if (fn.length === 2) { 236 | // fn(context, callback) 237 | promise = new Promise((resolve) => { 238 | fn(context, function (err, data) { 239 | if (err) { 240 | context.error(err) 241 | } 242 | data = data || {} 243 | resolve(data) 244 | }) 245 | }) 246 | } else { 247 | promise = fn(context) 248 | } 249 | if (!promise || (!(promise instanceof Promise) && (typeof promise.then !== 'function'))) { 250 | promise = Promise.resolve(promise) 251 | } 252 | return promise 253 | } 254 | 255 | // Imported from vue-router 256 | export function getLocation(base, mode) { 257 | let path = decodeURI(window.location.pathname) 258 | if (mode === 'hash') { 259 | return window.location.hash.replace(/^#\//, '') 260 | } 261 | if (base && path.indexOf(base) === 0) { 262 | path = path.slice(base.length) 263 | } 264 | return (path || '/') + window.location.search + window.location.hash 265 | } 266 | 267 | export function urlJoin() { 268 | return Array.prototype.slice.call(arguments).join('/').replace(/\/+/g, '/') 269 | } 270 | 271 | // Imported from path-to-regexp 272 | 273 | /** 274 | * Compile a string to a template function for the path. 275 | * 276 | * @param {string} str 277 | * @param {Object=} options 278 | * @return {!function(Object=, Object=)} 279 | */ 280 | export function compile(str, options) { 281 | return tokensToFunction(parse(str, options)) 282 | } 283 | 284 | export function getQueryDiff(toQuery, fromQuery) { 285 | const diff = {} 286 | const queries = { ...toQuery, ...fromQuery } 287 | for (const k in queries) { 288 | if (String(toQuery[k]) !== String(fromQuery[k])) { 289 | diff[k] = true 290 | } 291 | } 292 | return diff 293 | } 294 | 295 | export function normalizeError(err) { 296 | let message 297 | if (!(err.message || typeof err === 'string')) { 298 | try { 299 | message = JSON.stringify(err, null, 2) 300 | } catch (e) { 301 | message = `[${err.constructor.name}]` 302 | } 303 | } else { 304 | message = err.message || err 305 | } 306 | return { 307 | ...err, 308 | message, 309 | statusCode: (err.statusCode || err.status || (err.response && err.response.status) || 500) 310 | } 311 | } 312 | 313 | /** 314 | * The main path matching regexp utility. 315 | * 316 | * @type {RegExp} 317 | */ 318 | const PATH_REGEXP = new RegExp([ 319 | // Match escaped characters that would otherwise appear in future matches. 320 | // This allows the user to escape special characters that won't transform. 321 | '(\\\\.)', 322 | // Match Express-style parameters and un-named parameters with a prefix 323 | // and optional suffixes. Matches appear as: 324 | // 325 | // "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?", undefined] 326 | // "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined, undefined] 327 | // "/*" => ["/", undefined, undefined, undefined, undefined, "*"] 328 | '([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))' 329 | ].join('|'), 'g') 330 | 331 | /** 332 | * Parse a string for the raw tokens. 333 | * 334 | * @param {string} str 335 | * @param {Object=} options 336 | * @return {!Array} 337 | */ 338 | function parse(str, options) { 339 | const tokens = [] 340 | let key = 0 341 | let index = 0 342 | let path = '' 343 | const defaultDelimiter = (options && options.delimiter) || '/' 344 | let res 345 | 346 | while ((res = PATH_REGEXP.exec(str)) != null) { 347 | const m = res[0] 348 | const escaped = res[1] 349 | const offset = res.index 350 | path += str.slice(index, offset) 351 | index = offset + m.length 352 | 353 | // Ignore already escaped sequences. 354 | if (escaped) { 355 | path += escaped[1] 356 | continue 357 | } 358 | 359 | const next = str[index] 360 | const prefix = res[2] 361 | const name = res[3] 362 | const capture = res[4] 363 | const group = res[5] 364 | const modifier = res[6] 365 | const asterisk = res[7] 366 | 367 | // Push the current path onto the tokens. 368 | if (path) { 369 | tokens.push(path) 370 | path = '' 371 | } 372 | 373 | const partial = prefix != null && next != null && next !== prefix 374 | const repeat = modifier === '+' || modifier === '*' 375 | const optional = modifier === '?' || modifier === '*' 376 | const delimiter = res[2] || defaultDelimiter 377 | const pattern = capture || group 378 | 379 | tokens.push({ 380 | name: name || key++, 381 | prefix: prefix || '', 382 | delimiter, 383 | optional, 384 | repeat, 385 | partial, 386 | asterisk: Boolean(asterisk), 387 | pattern: pattern ? escapeGroup(pattern) : (asterisk ? '.*' : '[^' + escapeString(delimiter) + ']+?') 388 | }) 389 | } 390 | 391 | // Match any characters still remaining. 392 | if (index < str.length) { 393 | path += str.substr(index) 394 | } 395 | 396 | // If the path exists, push it onto the end. 397 | if (path) { 398 | tokens.push(path) 399 | } 400 | 401 | return tokens 402 | } 403 | 404 | /** 405 | * Prettier encoding of URI path segments. 406 | * 407 | * @param {string} 408 | * @return {string} 409 | */ 410 | function encodeURIComponentPretty(str) { 411 | return encodeURI(str).replace(/[/?#]/g, (c) => { 412 | return '%' + c.charCodeAt(0).toString(16).toUpperCase() 413 | }) 414 | } 415 | 416 | /** 417 | * Encode the asterisk parameter. Similar to `pretty`, but allows slashes. 418 | * 419 | * @param {string} 420 | * @return {string} 421 | */ 422 | function encodeAsterisk(str) { 423 | return encodeURI(str).replace(/[?#]/g, (c) => { 424 | return '%' + c.charCodeAt(0).toString(16).toUpperCase() 425 | }) 426 | } 427 | 428 | /** 429 | * Expose a method for transforming tokens into the path function. 430 | */ 431 | function tokensToFunction(tokens) { 432 | // Compile all the tokens into regexps. 433 | const matches = new Array(tokens.length) 434 | 435 | // Compile all the patterns before compilation. 436 | for (let i = 0; i < tokens.length; i++) { 437 | if (typeof tokens[i] === 'object') { 438 | matches[i] = new RegExp('^(?:' + tokens[i].pattern + ')$') 439 | } 440 | } 441 | 442 | return function (obj, opts) { 443 | let path = '' 444 | const data = obj || {} 445 | const options = opts || {} 446 | const encode = options.pretty ? encodeURIComponentPretty : encodeURIComponent 447 | 448 | for (let i = 0; i < tokens.length; i++) { 449 | const token = tokens[i] 450 | 451 | if (typeof token === 'string') { 452 | path += token 453 | 454 | continue 455 | } 456 | 457 | const value = data[token.name || 'pathMatch'] 458 | let segment 459 | 460 | if (value == null) { 461 | if (token.optional) { 462 | // Prepend partial segment prefixes. 463 | if (token.partial) { 464 | path += token.prefix 465 | } 466 | 467 | continue 468 | } else { 469 | throw new TypeError('Expected "' + token.name + '" to be defined') 470 | } 471 | } 472 | 473 | if (Array.isArray(value)) { 474 | if (!token.repeat) { 475 | throw new TypeError('Expected "' + token.name + '" to not repeat, but received `' + JSON.stringify(value) + '`') 476 | } 477 | 478 | if (value.length === 0) { 479 | if (token.optional) { 480 | continue 481 | } else { 482 | throw new TypeError('Expected "' + token.name + '" to not be empty') 483 | } 484 | } 485 | 486 | for (let j = 0; j < value.length; j++) { 487 | segment = encode(value[j]) 488 | 489 | if (!matches[i].test(segment)) { 490 | throw new TypeError('Expected all "' + token.name + '" to match "' + token.pattern + '", but received `' + JSON.stringify(segment) + '`') 491 | } 492 | 493 | path += (j === 0 ? token.prefix : token.delimiter) + segment 494 | } 495 | 496 | continue 497 | } 498 | 499 | segment = token.asterisk ? encodeAsterisk(value) : encode(value) 500 | 501 | if (!matches[i].test(segment)) { 502 | throw new TypeError('Expected "' + token.name + '" to match "' + token.pattern + '", but received "' + segment + '"') 503 | } 504 | 505 | path += token.prefix + segment 506 | } 507 | 508 | return path 509 | } 510 | } 511 | 512 | /** 513 | * Escape a regular expression string. 514 | * 515 | * @param {string} str 516 | * @return {string} 517 | */ 518 | function escapeString(str) { 519 | return str.replace(/([.+*?=^!:${}()[\]|/\\])/g, '\\$1') 520 | } 521 | 522 | /** 523 | * Escape the capturing group by escaping special characters and meaning. 524 | * 525 | * @param {string} group 526 | * @return {string} 527 | */ 528 | function escapeGroup(group) { 529 | return group.replace(/([=!:$/()])/g, '\\$1') 530 | } 531 | 532 | /** 533 | * Format given url, append query to url query string 534 | * 535 | * @param {string} url 536 | * @param {string} query 537 | * @return {string} 538 | */ 539 | function formatUrl(url, query) { 540 | let protocol 541 | const index = url.indexOf('://') 542 | if (index !== -1) { 543 | protocol = url.substring(0, index) 544 | url = url.substring(index + 3) 545 | } else if (url.startsWith('//')) { 546 | url = url.substring(2) 547 | } 548 | 549 | let parts = url.split('/') 550 | let result = (protocol ? protocol + '://' : '//') + parts.shift() 551 | 552 | let path = parts.filter(Boolean).join('/') 553 | let hash 554 | parts = path.split('#') 555 | if (parts.length === 2) { 556 | [path, hash] = parts 557 | } 558 | 559 | result += path ? '/' + path : '' 560 | 561 | if (query && JSON.stringify(query) !== '{}') { 562 | result += (url.split('?').length === 2 ? '&' : '?') + formatQuery(query) 563 | } 564 | result += hash ? '#' + hash : '' 565 | 566 | return result 567 | } 568 | 569 | /** 570 | * Transform data object to query string 571 | * 572 | * @param {object} query 573 | * @return {string} 574 | */ 575 | function formatQuery(query) { 576 | return Object.keys(query).sort().map((key) => { 577 | const val = query[key] 578 | if (val == null) { 579 | return '' 580 | } 581 | if (Array.isArray(val)) { 582 | return val.slice().map(val2 => [key, '=', val2].join('')).join('&') 583 | } 584 | return key + '=' + val 585 | }).filter(Boolean).join('&') 586 | } 587 | -------------------------------------------------------------------------------- /.nuxt/views/app.template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ HEAD }} 5 | 6 | 7 | {{ APP }} 8 | 9 | 10 | -------------------------------------------------------------------------------- /.nuxt/views/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Server error 5 | 6 | 7 | 10 | 11 | 12 |
13 |
14 | 15 |
Server error
16 |
An error occurred in the application and your page could not be served. If you are the application owner, check your logs for details.
17 |
18 | 21 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .nuxt/ 2 | coverage/ 3 | dist/ 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true 4 | } 5 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at info@cierra.de. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | We welcome everyone to submit pull requests with: 3 | - issue fixes 4 | - change suggestions 5 | - documentation updates 6 | 7 | However, not every pull request will automatically be accepted. We will review each carefully to make sure it is in line with 8 | the direction we want the package to continue in. This might mean that some pull requests are not accepted, or might stay 9 | unmerged until a place for them can be determined. 10 | 11 | 12 | ## Submitting changes 13 | When submitting a pull request, it is important to make sure to complete the following: 14 | - [ ] Add a descriptive header that explains in a single sentence what problem the PR solves. 15 | - [ ] Add a detailed description with animated screen-grab GIFs or screenshots visualizing how it works. 16 | - [ ] Explain why you think it should be implemented one way vs. another, highlight performance improvements, etc. 17 | 18 | ## Coding conventions 19 | Start reading our code and you'll get the hang of it. 20 | - This is open source software. Consider the people who will read your code, and make it look nice for them. It's sort of like driving a car: Perhaps you love doing donuts when you're alone, but with passengers the goal is to make the ride as smooth as possible. 21 | - Emphasis readability of code over patterns to reduce mental debt 22 | - Always add an empty line around structures (if statements, loops, etc.) 23 | 24 | Thanks! 25 | 26 | cierra Software Solutions 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Parse package for Nuxt.js 2 | [![CircleCI](https://circleci.com/gh/cierrateam/nuxt-parse/tree/master.svg?style=svg)](https://circleci.com/gh/cierrateam/nuxt-parse/tree/master) 3 | ![Cierra](https://img.shields.io/badge/Cierra-Open%20Source-orange.svg) 4 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/GeneaLabs/nova-map-marker-field/master/LICENSE) 5 | ![npm](https://img.shields.io/npm/dw/nuxt-parse) 6 | ![GitHub last commit (branch)](https://img.shields.io/github/last-commit/cierrateam/nuxt-parse/master) 7 | 8 | A parse module for Nuxt.js. 9 | 10 | ## Installation 11 | 12 | ```bash 13 | $ yarn add nuxt-parse # or npm install 14 | ``` 15 | 16 | Implement the module in `nuxt.config.js`: 17 | ``` 18 | ... 19 | modules: [ 20 | ['nuxt-parse', { 21 | appId: YOUR_APP_ID, 22 | javascriptKey: YOUR_JAVASCRIPT_KEY, 23 | serverUrl: OPTIONAL_SERVER_URL 24 | } 25 | ] 26 | ], 27 | ... 28 | ``` 29 | 30 | You don't have to provide the serverUrl if you're using the back4app service. 31 | 32 | ## Usage 33 | 34 | To access the parse instance you can use `this.$parse` anywhere you want to. For example to login you can use: 35 | ``` 36 | this.$parse.User.logIn('username', 'password') 37 | ``` 38 | 39 | ## Middleware 40 | 41 | To add the middleware to the client you can create a file called `middleware/auth.js` with the following content: 42 | ``` 43 | import Parse from 'parse'; 44 | export default function ({redirect}) { 45 | // If the user is not authenticated 46 | let currentUser = Parse.User.current(); 47 | if(!currentUser) 48 | return redirect('/register'); 49 | } 50 | ``` 51 | 52 | Then you're able to use the `middleware: 'auth'` option in your pages. 53 | 54 | ## Contributing 55 | Please observe and respect all aspects of the included Code of Conduct . 56 | 57 | ### Submitting Pull Requests 58 | Please review the Contribution Guidelines . Only PRs that meet all criterium will be accepted. 59 | -------------------------------------------------------------------------------- /lib/module.js: -------------------------------------------------------------------------------- 1 | // import { createMiddleware } from './module.middleware' 2 | import plugin from './module.plugin' 3 | import path from 'path' 4 | const optionName = 'nuxt-parse' 5 | 6 | module.exports = function(moduleOptions) { 7 | const consola = require('consola') 8 | const options = Object.assign( 9 | {}, 10 | this.options[optionName], 11 | moduleOptions || {} 12 | ) 13 | const { enabled } = options 14 | if (enabled === false) { 15 | consola.info('Skip activation of nuxt-parse module') 16 | return false 17 | } 18 | consola.info('Add nuxt-parse module to server middleware') 19 | 20 | this.addPlugin({ 21 | src: path.resolve(__dirname, 'module.plugin.js'), 22 | options: { 23 | appId: options.appId, 24 | javascriptKey: options.javascriptKey, 25 | serverUrl: (options.serverUrl || 'https://parseapi.back4app.com/') 26 | } 27 | }) 28 | 29 | return true 30 | } 31 | 32 | module.exports.meta = require('../package.json') 33 | -------------------------------------------------------------------------------- /lib/module.middleware.js: -------------------------------------------------------------------------------- 1 | import Middleware from '../middleware' 2 | import Vue from 'vue'; 3 | 4 | Middleware.auth = function ({ req, app, redirect }) { 5 | if (!process.server) { 6 | return 7 | } 8 | 9 | let currentUser = app.$parse.User.current(); 10 | 11 | if(!currentUser) { 12 | let url = '<%= options.redirectUrl %>'; 13 | return redirect(url); 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /lib/module.plugin.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | export default ( context, inject ) => { 4 | 5 | let Parse = require('parse'); 6 | 7 | Parse.initialize('<%= options.appId %>', '<%= options.javascriptKey %>'); 8 | 9 | Parse.serverURL = '<%= options.serverUrl %>' 10 | 11 | Vue.prototype.$parse = Parse; 12 | inject('parse', Parse); 13 | } 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt-parse", 3 | "version": "0.1.3", 4 | "description": "A parse module for Nuxt.js", 5 | "author": "Vittorio Emmermann", 6 | "keywords": [ 7 | "vue", 8 | "nuxt", 9 | "nuxt.js" 10 | ], 11 | "main": "lib/module.js", 12 | "license": "MIT", 13 | "scripts": { 14 | "dev": "nuxt test/fixture", 15 | "test": "jest", 16 | "test:unit": "jest --testRegex \"/test/unit/(.+)\\.test\\.js$\"", 17 | "test:system": "jest --testRegex \"/test/system/(.+)\\.test\\.js$\"", 18 | "test:coverage": "yarn test --coverage", 19 | "format": "prettier './**/*.{js,ts,json,vue}' --write" 20 | }, 21 | "devDependencies": { 22 | "jest": "29.3.1", 23 | "nuxt": "3.11.1", 24 | "prettier": "1.19.1", 25 | "puppeteer": "2.1.0" 26 | }, 27 | "jest": { 28 | "testEnvironment": "node", 29 | "collectCoverageFrom": [ 30 | "lib/**/*.{js,jsx}" 31 | ] 32 | }, 33 | "dependencies": { 34 | "consola": "^2.3.2", 35 | "parse": "^5.0.0" 36 | }, 37 | "directories": { 38 | "lib": "lib", 39 | "test": "test" 40 | }, 41 | "repository": { 42 | "type": "git", 43 | "url": "git+https://github.com/cierrateam/nuxt-parse.git" 44 | }, 45 | "bugs": { 46 | "url": "https://github.com/cierrateam/nuxt-parse/issues" 47 | }, 48 | "homepage": "https://github.com/cierrateam/nuxt-parse#readme" 49 | } 50 | -------------------------------------------------------------------------------- /test/fixture/nuxt.config.js: -------------------------------------------------------------------------------- 1 | const resolve = require('path').resolve 2 | 3 | const optionConfig = {} 4 | 5 | module.exports = { 6 | rootDir: resolve(__dirname, '../..'), 7 | srcDir: __dirname, 8 | modules: ['~/../../lib/module'], 9 | 'nuxt-parse': optionConfig, 10 | dev: process.env.NODE_ENV !== 'test' && process.env.NODE_ENV === 'production' 11 | } 12 | -------------------------------------------------------------------------------- /test/fixture/pages/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /test/system/module.test.js: -------------------------------------------------------------------------------- 1 | const puppeteer = require('puppeteer') 2 | const request = require('request-promise-native') 3 | 4 | const { Nuxt, Builder } = require('nuxt') 5 | const config = require('../fixture/nuxt.config') 6 | 7 | const url = path => `http://localhost:3000${path}` 8 | const get = path => request(url(path)) 9 | 10 | jest.setTimeout(10000) 11 | 12 | describe('module E2E test', () => { 13 | let nuxt 14 | let page 15 | let browser 16 | 17 | beforeAll(async () => { 18 | nuxt = new Nuxt(config) 19 | 20 | const createNuxt = async () => { 21 | await new Builder(nuxt).build() 22 | await nuxt.listen(3000) 23 | } 24 | const createBrowser = async () => { 25 | browser = await puppeteer.launch({ 26 | args: [ 27 | '--no-sandbox' 28 | ], 29 | headless: process.env.NODE_ENV !== 'development', 30 | timeout: 0 31 | }) 32 | page = await browser.newPage() 33 | } 34 | await Promise.all([createNuxt(), createBrowser()]) 35 | }, 300000) 36 | 37 | afterAll(async () => { 38 | await browser.close() 39 | await nuxt.close() 40 | }) 41 | 42 | test('WIP', () => { 43 | // TODO: write test 44 | expect(true).toBe(true) 45 | }) 46 | }) 47 | -------------------------------------------------------------------------------- /test/unit/module.middleware.test.js: -------------------------------------------------------------------------------- 1 | describe('module.middleware.js', () => { 2 | describe('sample', () => { 3 | it('should returns true', () => { 4 | expect(true).toBe(true) 5 | }) 6 | }) 7 | }) 8 | -------------------------------------------------------------------------------- /test/unit/module.test.js: -------------------------------------------------------------------------------- 1 | describe('module.js', () => { 2 | describe('sample', () => { 3 | it('should returns true', () => { 4 | expect(true).toBe(true) 5 | }) 6 | }) 7 | }) 8 | --------------------------------------------------------------------------------