feat: preliminary vue-app types

This commit is contained in:
Daniel Roe 2020-07-30 00:45:48 +01:00
parent e7dd27fa2a
commit 426cf1b3de
11 changed files with 84 additions and 13 deletions

View File

@ -0,0 +1,10 @@
declare module NodeJS {
interface Process {
browser: boolean
client: boolean
mode: 'spa' | 'universal'
modern: boolean
server: boolean
static: boolean
}
}

View File

@ -0,0 +1,6 @@
declare module 'nuxt-build/routes' {
import { RouteRecordRaw } from 'vue-router'
const _default: RouteRecordRaw[]
export default _default
}

View File

@ -0,0 +1,3 @@
interface Window {
__NUXT__?: Record<string, any>
}

View File

@ -1,28 +1,54 @@
import type { IncomingMessage, ServerResponse } from 'http'
import Hookable from 'hookable' import Hookable from 'hookable'
import type { App } from 'vue'
import type { Plugin } from './types'
import { defineGetter } from './utils' import { defineGetter } from './utils'
class Nuxt extends Hookable { export class Nuxt extends Hookable {
constructor ({ app, ssrContext, globalName }) { app: App<Element>
ssrContext?: Record<string, any>
globalName: string
context: {
req?: IncomingMessage
res?: ServerResponse
}
constructor({ app, ssrContext, globalName }: { app: Nuxt['app'], ssrContext?: Nuxt['ssrContext'], globalName: Nuxt['globalName'] }) {
super() super()
this.app = app this.app = app
this.ssrContext = ssrContext this.ssrContext = ssrContext
this.globalName = globalName this.globalName = globalName
} }
provide (name, value) { provide(name: string, value: any) {
const $name = '$' + name const $name = '$' + name
defineGetter(this.app, $name, value) defineGetter(this.app, $name, value)
defineGetter(this.app.config.globalProperties, $name, value) defineGetter(this.app.config.globalProperties, $name, value)
} }
} }
export async function init ({ app, plugins, ssrContext, globalName = 'nuxt' }) { interface InitOptions {
app: Nuxt['app']
plugins?: Plugin[]
ssrContext?: Nuxt['ssrContext']
globalName?: Nuxt['globalName']
}
export async function init({ app, plugins, ssrContext, globalName = 'nuxt' }: InitOptions) {
const nuxt = new Nuxt({ app, ssrContext, globalName }) const nuxt = new Nuxt({ app, ssrContext, globalName })
nuxt.provide('nuxt', nuxt) nuxt.provide('nuxt', nuxt)
const inject = nuxt.provide.bind(nuxt) const inject: Nuxt['provide'] = nuxt.provide.bind(nuxt)
for (const plugin of plugins) { for (const plugin of plugins) {
await plugin(nuxt, inject) await plugin(nuxt, inject)
} }
} }
declare module 'vue' {
interface App {
$nuxt: Nuxt
}
}

View File

@ -1,3 +1,5 @@
import type { Plugin } from 'nuxt/vue-app/types'
// import { h, defineComponent } from 'vue' // import { h, defineComponent } from 'vue'
import { RouterLink } from 'vue-router' import { RouterLink } from 'vue-router'
@ -5,7 +7,9 @@ import { RouterLink } from 'vue-router'
// extends: Link // extends: Link
// }) // })
export default function components ({ app }) { const components: Plugin = function ({ app }) {
app.component('NuxtLink', RouterLink) app.component('NuxtLink', RouterLink)
app.component('NLink', RouterLink) // TODO: deprecate app.component('NLink', RouterLink) // TODO: deprecate
} }
export default components

View File

@ -1,8 +1,11 @@
export default function legacy ({ app }) { import type { App } from 'vue'
import type { Plugin } from 'nuxt/vue-app/types'
const legacy: Plugin = function ({ app }) {
app.$nuxt.context = {} app.$nuxt.context = {}
if (process.client) { if (process.client) {
const legacyApp = { ...app } const legacyApp: App<Element> & { $root?: App<Element> } = { ...app }
legacyApp.$root = legacyApp legacyApp.$root = legacyApp
window[app.$nuxt.globalName] = legacyApp window[app.$nuxt.globalName] = legacyApp
} }
@ -13,3 +16,5 @@ export default function legacy ({ app }) {
app.$nuxt.context.res = ssrContext.res app.$nuxt.context.res = ssrContext.res
} }
} }
export default legacy

View File

@ -1,4 +1,6 @@
export default function preload ({ app }) { import type { Plugin } from 'nuxt/vue-app/types'
const preload: Plugin = function ({ app }) {
app.mixin({ app.mixin({
beforeCreate() { beforeCreate() {
const { _registeredComponents } = this.$nuxt.ssrContext const { _registeredComponents } = this.$nuxt.ssrContext
@ -7,3 +9,5 @@ export default function preload ({ app }) {
} }
}) })
} }
export default preload

View File

@ -1,9 +1,11 @@
import { ref } from 'vue' import { ref } from 'vue'
import { createRouter, createWebHistory, createMemoryHistory } from 'vue-router' import { createRouter, createWebHistory, createMemoryHistory } from 'vue-router'
import type { Plugin } from 'nuxt/vue-app/types'
import routes from 'nuxt-build/routes' import routes from 'nuxt-build/routes'
export default function router ({ app }) { const router: Plugin = function ({ app }) {
const routerHistory = process.client const routerHistory = process.client
? createWebHistory() ? createWebHistory()
: createMemoryHistory() : createMemoryHistory()
@ -35,3 +37,5 @@ export default function router ({ app }) {
}) })
} }
} }
export default router

View File

@ -1,4 +1,6 @@
export default function state ({ app }) { import type { Plugin } from 'nuxt/vue-app/types'
const state: Plugin = function ({ app }) {
if (process.server) { if (process.server) {
app.$nuxt.state = { app.$nuxt.state = {
serverRendered: true serverRendered: true
@ -11,3 +13,5 @@ export default function state ({ app }) {
app.$nuxt.state = window.__NUXT__ || {} app.$nuxt.state = window.__NUXT__ || {}
} }
} }
export default state

View File

@ -0,0 +1,5 @@
import type { Nuxt } from './nuxt';
export interface Plugin {
(nuxt: Nuxt, inject?: Nuxt['provide']): Promise<void> | void
}

View File

@ -1,3 +1,3 @@
export function defineGetter (obj, key, val) { export function defineGetter<K extends string | number | symbol, V> (obj: Record<K, V>, key: K, val: V) {
Object.defineProperty(obj, key, { get: () => val }) Object.defineProperty(obj, key, { get: () => val })
} }