Skip to content

Commit d77c7ad

Browse files
committed
feat(runtime-vapor): implement app plugin
1 parent b776f92 commit d77c7ad

File tree

3 files changed

+88
-0
lines changed

3 files changed

+88
-0
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { type Component, type Plugin, createVaporApp, inject } from '../src'
2+
;``
3+
describe('api: createApp', () => {
4+
test('use', () => {
5+
const PluginA: Plugin = app => app.provide('foo', 1)
6+
const PluginB: Plugin = {
7+
install: (app, arg1, arg2) => app.provide('bar', arg1 + arg2),
8+
}
9+
class PluginC {
10+
someProperty = {}
11+
static install() {
12+
app.provide('baz', 2)
13+
}
14+
}
15+
const PluginD: any = undefined
16+
17+
const Root: Component = {
18+
setup() {
19+
const foo = inject('foo')
20+
const bar = inject('bar')
21+
return document.createTextNode(`${foo},${bar}`)
22+
},
23+
}
24+
25+
const app = createVaporApp(Root)
26+
app.use(PluginA)
27+
app.use(PluginB, 1, 1)
28+
app.use(PluginC)
29+
30+
const root = document.createElement('div')
31+
app.mount(root)
32+
expect(root.innerHTML).toBe(`1,2`)
33+
34+
app.use(PluginA)
35+
expect(
36+
`Plugin has already been applied to target app`,
37+
).toHaveBeenWarnedTimes(1)
38+
39+
app.use(PluginD)
40+
expect(
41+
`A plugin must either be a function or an object with an "install" ` +
42+
`function.`,
43+
).toHaveBeenWarnedTimes(1)
44+
})
45+
})

packages/runtime-vapor/src/apiCreateVaporApp.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ export function createVaporApp(
2121
}
2222

2323
const context = createAppContext()
24+
const installedPlugins = new WeakSet()
25+
2426
let instance: ComponentInternalInstance
2527

2628
const app: App = {
@@ -40,6 +42,24 @@ export function createVaporApp(
4042
}
4143
},
4244

45+
use(plugin: Plugin, ...options: any[]) {
46+
if (installedPlugins.has(plugin)) {
47+
__DEV__ && warn(`Plugin has already been applied to target app.`)
48+
} else if (plugin && isFunction(plugin.install)) {
49+
installedPlugins.add(plugin)
50+
plugin.install(app, ...options)
51+
} else if (isFunction(plugin)) {
52+
installedPlugins.add(plugin)
53+
plugin(app, ...options)
54+
} else if (__DEV__) {
55+
warn(
56+
`A plugin must either be a function or an object with an "install" ` +
57+
`function.`,
58+
)
59+
}
60+
return app
61+
},
62+
4363
mount(rootContainer): any {
4464
if (!instance) {
4565
instance = createComponentInstance(
@@ -107,10 +127,30 @@ export function createAppContext(): AppContext {
107127
}
108128
}
109129

130+
type PluginInstallFunction<Options = any[]> = Options extends unknown[]
131+
? (app: App, ...options: Options) => any
132+
: (app: App, options: Options) => any
133+
134+
export type ObjectPlugin<Options = any[]> = {
135+
install: PluginInstallFunction<Options>
136+
}
137+
export type FunctionPlugin<Options = any[]> = PluginInstallFunction<Options> &
138+
Partial<ObjectPlugin<Options>>
139+
140+
export type Plugin<Options = any[]> =
141+
| FunctionPlugin<Options>
142+
| ObjectPlugin<Options>
143+
110144
export interface App {
111145
version: string
112146
config: AppConfig
113147

148+
use<Options extends unknown[]>(
149+
plugin: Plugin<Options>,
150+
...options: Options
151+
): this
152+
use<Options>(plugin: Plugin<Options>, options: Options): this
153+
114154
mount(
115155
rootContainer: ParentNode | string,
116156
isHydrate?: boolean,

packages/runtime-vapor/src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ export {
121121
type App,
122122
type AppConfig,
123123
type AppContext,
124+
type Plugin,
125+
type ObjectPlugin,
126+
type FunctionPlugin,
124127
} from './apiCreateVaporApp'
125128
export { createIf } from './apiCreateIf'
126129
export { createFor } from './apiCreateFor'

0 commit comments

Comments
 (0)