@@ -8,11 +8,18 @@ import { version } from "./constants"
8
8
import * as util from "./util"
9
9
const fsp = fs . promises
10
10
11
- // These fields are populated from the plugin's package.json.
12
11
interface Plugin extends pluginapi . Plugin {
12
+ /**
13
+ * These fields are populated from the plugin's package.json.
14
+ */
13
15
name : string
14
16
version : string
15
17
description : string
18
+
19
+ /**
20
+ * path to the node module on the disk.
21
+ */
22
+ modulePath : string
16
23
}
17
24
18
25
interface Application extends pluginapi . Application {
@@ -47,7 +54,6 @@ export class PluginAPI {
47
54
for ( const p of this . plugins ) {
48
55
const pluginApps = await p . applications ( )
49
56
50
- // TODO prevent duplicates
51
57
// Add plugin key to each app.
52
58
apps . push (
53
59
...pluginApps . map ( ( app ) => {
@@ -112,8 +118,15 @@ export class PluginAPI {
112
118
encoding : "utf8" ,
113
119
} )
114
120
const packageJSON : PackageJSON = JSON . parse ( str )
121
+ for ( const p of this . plugins ) {
122
+ if ( p . name === packageJSON . name ) {
123
+ this . logger . warn (
124
+ `ignoring duplicate plugin ${ q ( p . name ) } at ${ q ( dir ) } , using previously loaded ${ q ( p . modulePath ) } ` ,
125
+ )
126
+ return
127
+ }
128
+ }
115
129
const p = this . _loadPlugin ( dir , packageJSON )
116
- // TODO prevent duplicates
117
130
this . plugins . push ( p )
118
131
} catch ( err ) {
119
132
if ( err . code !== "ENOENT" ) {
@@ -145,6 +158,7 @@ export class PluginAPI {
145
158
name : packageJSON . name ,
146
159
version : packageJSON . version ,
147
160
description : packageJSON . description ,
161
+ modulePath : dir ,
148
162
...require ( dir ) ,
149
163
} as Plugin
150
164
0 commit comments