@shuvi/hook 1.0.22 → 1.0.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/hookGroup.d.ts +1 -48
- package/esm/hookGroup.js +7 -72
- package/esm/index.d.ts +1 -0
- package/esm/index.js +1 -0
- package/esm/types.d.ts +59 -0
- package/esm/types.js +1 -0
- package/esm/utils.d.ts +4 -0
- package/esm/utils.js +104 -0
- package/lib/hookGroup.d.ts +1 -48
- package/lib/hookGroup.js +7 -72
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/types.d.ts +59 -0
- package/lib/types.js +2 -0
- package/lib/utils.d.ts +4 -0
- package/lib/utils.js +110 -0
- package/package.json +1 -1
package/esm/hookGroup.d.ts
CHANGED
|
@@ -1,54 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare type PatchPluginParameter<T, C> = RemoveManagerVoidParameter<AddContextParameter<T, C>>;
|
|
3
|
-
export declare type AddContextParameter<T, C> = T extends (initalValue: infer I, extraArg: infer E) => infer R ? (initalValue: I, extraArg: E, context: C) => R : T;
|
|
4
|
-
export declare type AnyHook = SyncHook<any, any, any> | SyncBailHook<any, any, any> | SyncWaterfallHook<any, any> | AsyncParallelHook<any, any, any> | AsyncSeriesHook<any, any, any> | AsyncSeriesBailHook<any, any, any> | AsyncSeriesWaterfallHook<any, any>;
|
|
5
|
-
export interface HookMap {
|
|
6
|
-
[x: string]: AnyHook;
|
|
7
|
-
}
|
|
8
|
-
export declare type Setup<HM extends HookMap = {}> = (utils: {
|
|
9
|
-
addHooks: (hook: Partial<HM>) => void;
|
|
10
|
-
}) => void;
|
|
11
|
-
export declare type CreatePlugin<HM extends HookMap, C> = (pluginHandlers: IPluginHandlers<HM, C> & {
|
|
12
|
-
setup?: Setup;
|
|
13
|
-
}, options?: PluginOptions) => IPluginInstance<HM, C>;
|
|
14
|
-
export declare type HookManager<HM extends HookMap, C> = {
|
|
15
|
-
createPlugin: CreatePlugin<HM, C>;
|
|
16
|
-
usePlugin: (...plugins: IPluginInstance<HM, C>[]) => void;
|
|
17
|
-
runner: RunnerType<HM>;
|
|
18
|
-
setContext: (context: C) => void;
|
|
19
|
-
clear: () => void;
|
|
20
|
-
addHooks: <EHM extends HookMap>(hook: Partial<EHM>) => void;
|
|
21
|
-
hooks: HM;
|
|
22
|
-
getPlugins: () => IPluginInstance<HM, C>[];
|
|
23
|
-
};
|
|
24
|
-
export declare type RunnerType<HM> = {
|
|
25
|
-
[K in keyof HM]: HookRunnerType<HM[K]>;
|
|
26
|
-
} & {
|
|
27
|
-
setup: Setup;
|
|
28
|
-
};
|
|
29
|
-
export declare type HookRunnerType<H> = H extends SyncHook<infer T, infer E, infer R> ? SyncHook<T, E, R>['run'] : H extends SyncBailHook<infer T, infer E, infer R> ? SyncBailHook<T, E, R>['run'] : H extends SyncWaterfallHook<infer T, infer E> ? SyncWaterfallHook<T, E>['run'] : H extends AsyncParallelHook<infer T, infer E, infer R> ? AsyncParallelHook<T, E, R>['run'] : H extends AsyncSeriesHook<infer T, infer E, infer R> ? AsyncSeriesHook<T, E, R>['run'] : H extends AsyncSeriesBailHook<infer T, infer E, infer R> ? AsyncSeriesBailHook<T, E, R>['run'] : H extends AsyncSeriesWaterfallHook<infer T, infer E> ? AsyncSeriesWaterfallHook<T, E>['run'] : never;
|
|
30
|
-
export declare type IPluginInstance<HM, C> = {
|
|
31
|
-
handlers: IPluginHandlers<HM, C>;
|
|
32
|
-
PLUGIN_SYMBOL: 'PLUGIN_SYMBOL';
|
|
33
|
-
} & Required<PluginOptions>;
|
|
34
|
-
export declare type IPluginHandlers<HM, C> = Partial<IPluginHandlersFullMap<HM, C>>;
|
|
35
|
-
export declare type IPluginHandlersFullMap<HM, C> = {
|
|
36
|
-
[K in keyof HM]: HM[K] extends SyncHook<infer T, infer E, infer R> ? PatchPluginParameter<SyncHookHandler<T, E, R>, C> : HM[K] extends SyncBailHook<infer T, infer E, infer R> ? PatchPluginParameter<SyncBailHookHandler<T, E, R>, C> : HM[K] extends SyncWaterfallHook<infer T, infer E> ? PatchPluginParameter<SyncWaterfallHookHandler<T, E>, C> : HM[K] extends AsyncParallelHook<infer T, infer E, infer R> ? PatchPluginParameter<AsyncParallelHookHandler<T, E, R>, C> : HM[K] extends AsyncSeriesHook<infer T, infer E, infer R> ? PatchPluginParameter<AsyncSeriesHookHandler<T, E, R>, C> : HM[K] extends AsyncSeriesBailHook<infer T, infer E, infer R> ? PatchPluginParameter<AsyncSeriesBailHookHandler<T, E, R>, C> : HM[K] extends AsyncSeriesWaterfallHook<infer T, infer E> ? PatchPluginParameter<AsyncSeriesWaterfallHookHandler<T, E>, C> : never;
|
|
37
|
-
};
|
|
38
|
-
export declare type PluginOptions = {
|
|
39
|
-
name?: string;
|
|
40
|
-
pre?: string[];
|
|
41
|
-
post?: string[];
|
|
42
|
-
rivals?: string[];
|
|
43
|
-
required?: string[];
|
|
44
|
-
order?: number;
|
|
45
|
-
group?: number;
|
|
46
|
-
[x: string]: any;
|
|
47
|
-
};
|
|
1
|
+
import { IPluginHandlers, IPluginInstance, HookManager, HookMap, PluginOptions } from './types';
|
|
48
2
|
export declare const isPluginInstance: <T extends IPluginInstance<any, any> = IPluginInstance<any, any>>(plugin: any) => plugin is T;
|
|
49
3
|
export declare type ArrayElements<T extends {}> = {
|
|
50
4
|
[K in keyof T]: T[K][];
|
|
51
5
|
};
|
|
52
6
|
export declare function createPlugin<HM extends HookMap, C = void>(pluginHandlers: IPluginHandlers<HM, C>, options?: PluginOptions): IPluginInstance<HM, C>;
|
|
53
7
|
export declare const createHookManager: <HM extends HookMap, C = void>(hookMap: HM, hasContext?: boolean) => HookManager<HM, C>;
|
|
54
|
-
export declare type RemoveManagerVoidParameter<T> = T extends (initalValue: infer I, extraArg: infer E, context: infer C) => infer R ? null extends I ? null extends E ? null extends C ? (initialValue: I, extraArg: E, context: C) => R : void extends C ? (initialValue: I, extraArg: E) => R : (initialValue: I, extraArg: E, context: C) => R : void extends E ? null extends C ? (initialValue: I, context: C) => R : void extends C ? (initialValue: I) => R : (initialValue: I, context: C) => R : null extends C ? (initialValue: I, extraArg: E, context: C) => R : void extends C ? (initialValue: I, extraArg: E) => R : (initialValue: I, extraArg: E, context: C) => R : void extends I ? null extends E ? null extends C ? (extraArg: E, context: C) => R : void extends C ? (extraArg: E) => R : (extraArg: E, context: C) => R : void extends E ? null extends C ? (context: C) => R : void extends C ? () => R : (context: C) => R : null extends C ? (extraArg: E, context: C) => R : void extends C ? (extraArg: E) => R : (extraArg: E, context: C) => R : null extends E ? null extends C ? (initialValue: I, extraArg: E, context: C) => R : void extends C ? (initialValue: I, extraArg: E) => R : (initialValue: I, extraArg: E, context: C) => R : void extends E ? null extends C ? (initialValue: I, context: C) => R : void extends C ? (initialValue: I) => R : (initialValue: I, context: C) => R : null extends C ? (initialValue: I, extraArg: E, context: C) => R : void extends C ? (initialValue: I, extraArg: E) => R : (initialValue: I, extraArg: E, context: C) => R : T;
|
package/esm/hookGroup.js
CHANGED
|
@@ -1,81 +1,17 @@
|
|
|
1
1
|
import { createSyncHook, createSyncBailHook, createSyncWaterfallHook, createAsyncParallelHook, createAsyncSeriesWaterfallHook, createAsyncSeriesBailHook, createAsyncSeriesHook } from './hooks';
|
|
2
|
+
import { verifyPlugins, sortPlugins } from './utils';
|
|
2
3
|
const DEFAULT_OPTIONS = {
|
|
3
4
|
name: 'untitled',
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
before: [],
|
|
6
|
+
after: [],
|
|
7
|
+
conflict: [],
|
|
7
8
|
required: [],
|
|
8
|
-
order: 0,
|
|
9
9
|
group: 0
|
|
10
10
|
};
|
|
11
11
|
const PLUGIN_SYMBOL = 'PLUGIN_SYMBOL';
|
|
12
12
|
export const isPluginInstance = (plugin) => plugin &&
|
|
13
13
|
plugin.hasOwnProperty(PLUGIN_SYMBOL) &&
|
|
14
14
|
plugin.PLUGIN_SYMBOL === PLUGIN_SYMBOL;
|
|
15
|
-
const sortPlugins = (input) => {
|
|
16
|
-
let plugins = input.slice();
|
|
17
|
-
plugins.sort((a, b) => {
|
|
18
|
-
// sort by group first
|
|
19
|
-
if (a.group === b.group) {
|
|
20
|
-
return a.order - b.order;
|
|
21
|
-
}
|
|
22
|
-
else {
|
|
23
|
-
return a.group - b.group;
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
for (let i = 0; i < plugins.length; i++) {
|
|
27
|
-
let plugin = plugins[i];
|
|
28
|
-
if (plugin.pre) {
|
|
29
|
-
for (const pre of plugin.pre) {
|
|
30
|
-
for (let j = i + 1; j < plugins.length; j++) {
|
|
31
|
-
if (plugins[j].name === pre) {
|
|
32
|
-
plugins = [
|
|
33
|
-
...plugins.slice(0, i),
|
|
34
|
-
plugins[j],
|
|
35
|
-
...plugins.slice(i, j),
|
|
36
|
-
...plugins.slice(j + 1, plugins.length)
|
|
37
|
-
];
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
if (plugin.post) {
|
|
43
|
-
for (const post of plugin.post) {
|
|
44
|
-
for (let j = 0; j < i; j++) {
|
|
45
|
-
if (plugins[j].name === post) {
|
|
46
|
-
plugins = [
|
|
47
|
-
...plugins.slice(0, j),
|
|
48
|
-
...plugins.slice(j + 1, i + 1),
|
|
49
|
-
plugins[j],
|
|
50
|
-
...plugins.slice(i + 1, plugins.length)
|
|
51
|
-
];
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return plugins;
|
|
58
|
-
};
|
|
59
|
-
const checkPlugins = (plugins) => {
|
|
60
|
-
for (const origin of plugins) {
|
|
61
|
-
if (origin.rivals) {
|
|
62
|
-
for (const rival of origin.rivals) {
|
|
63
|
-
for (const plugin of plugins) {
|
|
64
|
-
if (rival === plugin.name) {
|
|
65
|
-
throw new Error(`${origin.name} has rival ${plugin.name}`);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
if (origin.required) {
|
|
71
|
-
for (const required of origin.required) {
|
|
72
|
-
if (!plugins.some(plugin => plugin.name === required)) {
|
|
73
|
-
throw new Error(`The plugin: ${required} is required when plugin: ${origin.name} is exist.`);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
15
|
function uuid() {
|
|
80
16
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
81
17
|
var r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;
|
|
@@ -136,10 +72,9 @@ export const createHookManager = (hookMap, hasContext = true) => {
|
|
|
136
72
|
_plugins.push(...plugins);
|
|
137
73
|
};
|
|
138
74
|
const load = () => {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
plugins.forEach(plugin => {
|
|
75
|
+
verifyPlugins(_plugins);
|
|
76
|
+
_plugins = sortPlugins(_plugins);
|
|
77
|
+
_plugins.forEach(plugin => {
|
|
143
78
|
const handlers = plugin.handlers;
|
|
144
79
|
let hookName;
|
|
145
80
|
for (hookName in handlers) {
|
package/esm/index.d.ts
CHANGED
package/esm/index.js
CHANGED
package/esm/types.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { SyncHook, SyncBailHook, SyncWaterfallHook, AsyncParallelHook, AsyncSeriesWaterfallHook, SyncHookHandler, SyncBailHookHandler, SyncWaterfallHookHandler, AsyncParallelHookHandler, AsyncSeriesWaterfallHookHandler, AsyncSeriesHook, AsyncSeriesBailHook, AsyncSeriesHookHandler, AsyncSeriesBailHookHandler } from './hooks';
|
|
2
|
+
export declare type PatchPluginParameter<T, C> = RemoveManagerVoidParameter<AddContextParameter<T, C>>;
|
|
3
|
+
export declare type AddContextParameter<T, C> = T extends (initalValue: infer I, extraArg: infer E) => infer R ? (initalValue: I, extraArg: E, context: C) => R : T;
|
|
4
|
+
export declare type AnyHook = SyncHook<any, any, any> | SyncBailHook<any, any, any> | SyncWaterfallHook<any, any> | AsyncParallelHook<any, any, any> | AsyncSeriesHook<any, any, any> | AsyncSeriesBailHook<any, any, any> | AsyncSeriesWaterfallHook<any, any>;
|
|
5
|
+
export interface HookMap {
|
|
6
|
+
[x: string]: AnyHook;
|
|
7
|
+
}
|
|
8
|
+
export declare type Setup<HM extends HookMap = {}> = (utils: {
|
|
9
|
+
addHooks: (hook: Partial<HM>) => void;
|
|
10
|
+
}) => void;
|
|
11
|
+
export declare type CreatePlugin<HM extends HookMap, C> = (pluginHandlers: IPluginHandlers<HM, C> & {
|
|
12
|
+
setup?: Setup;
|
|
13
|
+
}, options?: PluginOptions) => IPluginInstance<HM, C>;
|
|
14
|
+
export declare type HookManager<HM extends HookMap, C> = {
|
|
15
|
+
createPlugin: CreatePlugin<HM, C>;
|
|
16
|
+
usePlugin: (...plugins: IPluginInstance<HM, C>[]) => void;
|
|
17
|
+
runner: RunnerType<HM>;
|
|
18
|
+
setContext: (context: C) => void;
|
|
19
|
+
clear: () => void;
|
|
20
|
+
addHooks: <EHM extends HookMap>(hook: Partial<EHM>) => void;
|
|
21
|
+
hooks: HM;
|
|
22
|
+
getPlugins: () => IPluginInstance<HM, C>[];
|
|
23
|
+
};
|
|
24
|
+
export declare type RunnerType<HM> = {
|
|
25
|
+
[K in keyof HM]: HookRunnerType<HM[K]>;
|
|
26
|
+
} & {
|
|
27
|
+
setup: Setup;
|
|
28
|
+
};
|
|
29
|
+
export declare type HookRunnerType<H> = H extends SyncHook<infer T, infer E, infer R> ? SyncHook<T, E, R>['run'] : H extends SyncBailHook<infer T, infer E, infer R> ? SyncBailHook<T, E, R>['run'] : H extends SyncWaterfallHook<infer T, infer E> ? SyncWaterfallHook<T, E>['run'] : H extends AsyncParallelHook<infer T, infer E, infer R> ? AsyncParallelHook<T, E, R>['run'] : H extends AsyncSeriesHook<infer T, infer E, infer R> ? AsyncSeriesHook<T, E, R>['run'] : H extends AsyncSeriesBailHook<infer T, infer E, infer R> ? AsyncSeriesBailHook<T, E, R>['run'] : H extends AsyncSeriesWaterfallHook<infer T, infer E> ? AsyncSeriesWaterfallHook<T, E>['run'] : never;
|
|
30
|
+
export declare type IPluginInstance<HM, C> = {
|
|
31
|
+
handlers: IPluginHandlers<HM, C>;
|
|
32
|
+
PLUGIN_SYMBOL: 'PLUGIN_SYMBOL';
|
|
33
|
+
} & Required<PluginOptions>;
|
|
34
|
+
export declare type IPluginHandlers<HM, C> = Partial<IPluginHandlersFullMap<HM, C>>;
|
|
35
|
+
export declare type IPluginHandlersFullMap<HM, C> = {
|
|
36
|
+
[K in keyof HM]: HM[K] extends SyncHook<infer T, infer E, infer R> ? PatchPluginParameter<SyncHookHandler<T, E, R>, C> : HM[K] extends SyncBailHook<infer T, infer E, infer R> ? PatchPluginParameter<SyncBailHookHandler<T, E, R>, C> : HM[K] extends SyncWaterfallHook<infer T, infer E> ? PatchPluginParameter<SyncWaterfallHookHandler<T, E>, C> : HM[K] extends AsyncParallelHook<infer T, infer E, infer R> ? PatchPluginParameter<AsyncParallelHookHandler<T, E, R>, C> : HM[K] extends AsyncSeriesHook<infer T, infer E, infer R> ? PatchPluginParameter<AsyncSeriesHookHandler<T, E, R>, C> : HM[K] extends AsyncSeriesBailHook<infer T, infer E, infer R> ? PatchPluginParameter<AsyncSeriesBailHookHandler<T, E, R>, C> : HM[K] extends AsyncSeriesWaterfallHook<infer T, infer E> ? PatchPluginParameter<AsyncSeriesWaterfallHookHandler<T, E>, C> : never;
|
|
37
|
+
};
|
|
38
|
+
export declare type PluginOptions = {
|
|
39
|
+
name?: string;
|
|
40
|
+
/** current plugin should before these configured plugins.
|
|
41
|
+
* only works for same group
|
|
42
|
+
*/
|
|
43
|
+
before?: string[];
|
|
44
|
+
/** current plugin should after these configured plugins.
|
|
45
|
+
* only works for same group.
|
|
46
|
+
*/
|
|
47
|
+
after?: string[];
|
|
48
|
+
/** current plugin should not be used with these configured plugins */
|
|
49
|
+
conflict?: string[];
|
|
50
|
+
/** current plugin should be used with these configured plugins */
|
|
51
|
+
required?: string[];
|
|
52
|
+
/** current plugin group.
|
|
53
|
+
* smaller group will be executed first
|
|
54
|
+
* 0: default
|
|
55
|
+
*/
|
|
56
|
+
group?: number;
|
|
57
|
+
[x: string]: any;
|
|
58
|
+
};
|
|
59
|
+
export declare type RemoveManagerVoidParameter<T> = T extends (initalValue: infer I, extraArg: infer E, context: infer C) => infer R ? null extends I ? null extends E ? null extends C ? (initialValue: I, extraArg: E, context: C) => R : void extends C ? (initialValue: I, extraArg: E) => R : (initialValue: I, extraArg: E, context: C) => R : void extends E ? null extends C ? (initialValue: I, context: C) => R : void extends C ? (initialValue: I) => R : (initialValue: I, context: C) => R : null extends C ? (initialValue: I, extraArg: E, context: C) => R : void extends C ? (initialValue: I, extraArg: E) => R : (initialValue: I, extraArg: E, context: C) => R : void extends I ? null extends E ? null extends C ? (extraArg: E, context: C) => R : void extends C ? (extraArg: E) => R : (extraArg: E, context: C) => R : void extends E ? null extends C ? (context: C) => R : void extends C ? () => R : (context: C) => R : null extends C ? (extraArg: E, context: C) => R : void extends C ? (extraArg: E) => R : (extraArg: E, context: C) => R : null extends E ? null extends C ? (initialValue: I, extraArg: E, context: C) => R : void extends C ? (initialValue: I, extraArg: E) => R : (initialValue: I, extraArg: E, context: C) => R : void extends E ? null extends C ? (initialValue: I, context: C) => R : void extends C ? (initialValue: I) => R : (initialValue: I, context: C) => R : null extends C ? (initialValue: I, extraArg: E, context: C) => R : void extends C ? (initialValue: I, extraArg: E) => R : (initialValue: I, extraArg: E, context: C) => R : T;
|
package/esm/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/esm/utils.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { IPluginInstance } from './types';
|
|
2
|
+
export declare const sortPluginsByRelationShip: <T extends IPluginInstance<any, any>[]>(input: T) => T;
|
|
3
|
+
export declare const sortPlugins: <T extends IPluginInstance<any, any>[]>(input: T) => T;
|
|
4
|
+
export declare const verifyPlugins: (plugins: IPluginInstance<any, any>[]) => void;
|
package/esm/utils.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
export const sortPluginsByRelationShip = (input) => {
|
|
2
|
+
const plugins = new Map();
|
|
3
|
+
/**
|
|
4
|
+
* the key is the end point of the edge
|
|
5
|
+
* In this way, we can easily find the plugin with zero in-degree
|
|
6
|
+
*/
|
|
7
|
+
const edges = new Map();
|
|
8
|
+
const addEdge = (start, end) => {
|
|
9
|
+
if (!edges.has(end)) {
|
|
10
|
+
edges.set(end, new Set());
|
|
11
|
+
}
|
|
12
|
+
edges.get(end).add(start);
|
|
13
|
+
};
|
|
14
|
+
// Firstly, set plugins into map
|
|
15
|
+
input.forEach(plugin => {
|
|
16
|
+
plugins.set(plugin.name, plugin);
|
|
17
|
+
});
|
|
18
|
+
input.forEach(plugin => {
|
|
19
|
+
if (!edges.has(plugin.name)) {
|
|
20
|
+
edges.set(plugin.name, new Set());
|
|
21
|
+
}
|
|
22
|
+
if (plugin.before) {
|
|
23
|
+
plugin.before.forEach(name => {
|
|
24
|
+
// If the plugin is not in the input, we will ignore it
|
|
25
|
+
if (plugins.has(name)) {
|
|
26
|
+
addEdge(plugin.name, name);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
if (plugin.after) {
|
|
31
|
+
plugin.after.forEach(name => {
|
|
32
|
+
// If the plugin is not in the input, we will ignore it
|
|
33
|
+
if (plugins.has(name)) {
|
|
34
|
+
addEdge(name, plugin.name);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
const sorted = [];
|
|
40
|
+
while (edges.size > 0) {
|
|
41
|
+
let hasZeroInDegree = false;
|
|
42
|
+
edges.forEach((value, key) => {
|
|
43
|
+
if (value.size === 0) {
|
|
44
|
+
hasZeroInDegree = true;
|
|
45
|
+
sorted.push(plugins.get(key));
|
|
46
|
+
edges.delete(key);
|
|
47
|
+
edges.forEach(v => {
|
|
48
|
+
v.delete(key);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
if (!hasZeroInDegree) {
|
|
53
|
+
throw new Error(`Plugin circular dependency detected: ${Array.from(edges.keys()).join(', ')}. Please ensure the plugins have correct 'before' and 'after' property.`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return sorted;
|
|
57
|
+
};
|
|
58
|
+
export const sortPlugins = (input) => {
|
|
59
|
+
const groupMap = new Map();
|
|
60
|
+
input.forEach(plugin => {
|
|
61
|
+
if (!groupMap.has(plugin.group)) {
|
|
62
|
+
groupMap.set(plugin.group, []);
|
|
63
|
+
}
|
|
64
|
+
groupMap.get(plugin.group).push(plugin);
|
|
65
|
+
});
|
|
66
|
+
const groupNumbers = Array.from(groupMap.keys());
|
|
67
|
+
const sortedGroupNumbers = groupNumbers.sort((a, b) => a - b);
|
|
68
|
+
const sorted = [];
|
|
69
|
+
sortedGroupNumbers.forEach(groupNumber => {
|
|
70
|
+
sorted.push(...sortPluginsByRelationShip(groupMap.get(groupNumber)));
|
|
71
|
+
});
|
|
72
|
+
return sorted;
|
|
73
|
+
};
|
|
74
|
+
export const verifyPlugins = (plugins) => {
|
|
75
|
+
const names = new Set();
|
|
76
|
+
for (const current of plugins) {
|
|
77
|
+
if (typeof current.name !== 'string') {
|
|
78
|
+
throw new Error(`Plugin name must be string type.`);
|
|
79
|
+
}
|
|
80
|
+
if (!current.name) {
|
|
81
|
+
throw new Error(`Plugin name must be non-empty string.`);
|
|
82
|
+
}
|
|
83
|
+
if (names.has(current.name)) {
|
|
84
|
+
throw new Error(`Plugin name duplication detected: ${current.name}.`);
|
|
85
|
+
}
|
|
86
|
+
names.add(current.name);
|
|
87
|
+
if (current.conflict) {
|
|
88
|
+
for (const conflict of current.conflict) {
|
|
89
|
+
for (const plugin of plugins) {
|
|
90
|
+
if (conflict === plugin.name) {
|
|
91
|
+
throw new Error(`Plugin conflict detected: ${current.name} has conflict with ${plugin.name}.`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (current.required) {
|
|
97
|
+
for (const required of current.required) {
|
|
98
|
+
if (!plugins.some(plugin => plugin.name === required)) {
|
|
99
|
+
throw new Error(`Plugin missing detected: ${required} is required by ${current.name}.`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
package/lib/hookGroup.d.ts
CHANGED
|
@@ -1,54 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare type PatchPluginParameter<T, C> = RemoveManagerVoidParameter<AddContextParameter<T, C>>;
|
|
3
|
-
export declare type AddContextParameter<T, C> = T extends (initalValue: infer I, extraArg: infer E) => infer R ? (initalValue: I, extraArg: E, context: C) => R : T;
|
|
4
|
-
export declare type AnyHook = SyncHook<any, any, any> | SyncBailHook<any, any, any> | SyncWaterfallHook<any, any> | AsyncParallelHook<any, any, any> | AsyncSeriesHook<any, any, any> | AsyncSeriesBailHook<any, any, any> | AsyncSeriesWaterfallHook<any, any>;
|
|
5
|
-
export interface HookMap {
|
|
6
|
-
[x: string]: AnyHook;
|
|
7
|
-
}
|
|
8
|
-
export declare type Setup<HM extends HookMap = {}> = (utils: {
|
|
9
|
-
addHooks: (hook: Partial<HM>) => void;
|
|
10
|
-
}) => void;
|
|
11
|
-
export declare type CreatePlugin<HM extends HookMap, C> = (pluginHandlers: IPluginHandlers<HM, C> & {
|
|
12
|
-
setup?: Setup;
|
|
13
|
-
}, options?: PluginOptions) => IPluginInstance<HM, C>;
|
|
14
|
-
export declare type HookManager<HM extends HookMap, C> = {
|
|
15
|
-
createPlugin: CreatePlugin<HM, C>;
|
|
16
|
-
usePlugin: (...plugins: IPluginInstance<HM, C>[]) => void;
|
|
17
|
-
runner: RunnerType<HM>;
|
|
18
|
-
setContext: (context: C) => void;
|
|
19
|
-
clear: () => void;
|
|
20
|
-
addHooks: <EHM extends HookMap>(hook: Partial<EHM>) => void;
|
|
21
|
-
hooks: HM;
|
|
22
|
-
getPlugins: () => IPluginInstance<HM, C>[];
|
|
23
|
-
};
|
|
24
|
-
export declare type RunnerType<HM> = {
|
|
25
|
-
[K in keyof HM]: HookRunnerType<HM[K]>;
|
|
26
|
-
} & {
|
|
27
|
-
setup: Setup;
|
|
28
|
-
};
|
|
29
|
-
export declare type HookRunnerType<H> = H extends SyncHook<infer T, infer E, infer R> ? SyncHook<T, E, R>['run'] : H extends SyncBailHook<infer T, infer E, infer R> ? SyncBailHook<T, E, R>['run'] : H extends SyncWaterfallHook<infer T, infer E> ? SyncWaterfallHook<T, E>['run'] : H extends AsyncParallelHook<infer T, infer E, infer R> ? AsyncParallelHook<T, E, R>['run'] : H extends AsyncSeriesHook<infer T, infer E, infer R> ? AsyncSeriesHook<T, E, R>['run'] : H extends AsyncSeriesBailHook<infer T, infer E, infer R> ? AsyncSeriesBailHook<T, E, R>['run'] : H extends AsyncSeriesWaterfallHook<infer T, infer E> ? AsyncSeriesWaterfallHook<T, E>['run'] : never;
|
|
30
|
-
export declare type IPluginInstance<HM, C> = {
|
|
31
|
-
handlers: IPluginHandlers<HM, C>;
|
|
32
|
-
PLUGIN_SYMBOL: 'PLUGIN_SYMBOL';
|
|
33
|
-
} & Required<PluginOptions>;
|
|
34
|
-
export declare type IPluginHandlers<HM, C> = Partial<IPluginHandlersFullMap<HM, C>>;
|
|
35
|
-
export declare type IPluginHandlersFullMap<HM, C> = {
|
|
36
|
-
[K in keyof HM]: HM[K] extends SyncHook<infer T, infer E, infer R> ? PatchPluginParameter<SyncHookHandler<T, E, R>, C> : HM[K] extends SyncBailHook<infer T, infer E, infer R> ? PatchPluginParameter<SyncBailHookHandler<T, E, R>, C> : HM[K] extends SyncWaterfallHook<infer T, infer E> ? PatchPluginParameter<SyncWaterfallHookHandler<T, E>, C> : HM[K] extends AsyncParallelHook<infer T, infer E, infer R> ? PatchPluginParameter<AsyncParallelHookHandler<T, E, R>, C> : HM[K] extends AsyncSeriesHook<infer T, infer E, infer R> ? PatchPluginParameter<AsyncSeriesHookHandler<T, E, R>, C> : HM[K] extends AsyncSeriesBailHook<infer T, infer E, infer R> ? PatchPluginParameter<AsyncSeriesBailHookHandler<T, E, R>, C> : HM[K] extends AsyncSeriesWaterfallHook<infer T, infer E> ? PatchPluginParameter<AsyncSeriesWaterfallHookHandler<T, E>, C> : never;
|
|
37
|
-
};
|
|
38
|
-
export declare type PluginOptions = {
|
|
39
|
-
name?: string;
|
|
40
|
-
pre?: string[];
|
|
41
|
-
post?: string[];
|
|
42
|
-
rivals?: string[];
|
|
43
|
-
required?: string[];
|
|
44
|
-
order?: number;
|
|
45
|
-
group?: number;
|
|
46
|
-
[x: string]: any;
|
|
47
|
-
};
|
|
1
|
+
import { IPluginHandlers, IPluginInstance, HookManager, HookMap, PluginOptions } from './types';
|
|
48
2
|
export declare const isPluginInstance: <T extends IPluginInstance<any, any> = IPluginInstance<any, any>>(plugin: any) => plugin is T;
|
|
49
3
|
export declare type ArrayElements<T extends {}> = {
|
|
50
4
|
[K in keyof T]: T[K][];
|
|
51
5
|
};
|
|
52
6
|
export declare function createPlugin<HM extends HookMap, C = void>(pluginHandlers: IPluginHandlers<HM, C>, options?: PluginOptions): IPluginInstance<HM, C>;
|
|
53
7
|
export declare const createHookManager: <HM extends HookMap, C = void>(hookMap: HM, hasContext?: boolean) => HookManager<HM, C>;
|
|
54
|
-
export declare type RemoveManagerVoidParameter<T> = T extends (initalValue: infer I, extraArg: infer E, context: infer C) => infer R ? null extends I ? null extends E ? null extends C ? (initialValue: I, extraArg: E, context: C) => R : void extends C ? (initialValue: I, extraArg: E) => R : (initialValue: I, extraArg: E, context: C) => R : void extends E ? null extends C ? (initialValue: I, context: C) => R : void extends C ? (initialValue: I) => R : (initialValue: I, context: C) => R : null extends C ? (initialValue: I, extraArg: E, context: C) => R : void extends C ? (initialValue: I, extraArg: E) => R : (initialValue: I, extraArg: E, context: C) => R : void extends I ? null extends E ? null extends C ? (extraArg: E, context: C) => R : void extends C ? (extraArg: E) => R : (extraArg: E, context: C) => R : void extends E ? null extends C ? (context: C) => R : void extends C ? () => R : (context: C) => R : null extends C ? (extraArg: E, context: C) => R : void extends C ? (extraArg: E) => R : (extraArg: E, context: C) => R : null extends E ? null extends C ? (initialValue: I, extraArg: E, context: C) => R : void extends C ? (initialValue: I, extraArg: E) => R : (initialValue: I, extraArg: E, context: C) => R : void extends E ? null extends C ? (initialValue: I, context: C) => R : void extends C ? (initialValue: I) => R : (initialValue: I, context: C) => R : null extends C ? (initialValue: I, extraArg: E, context: C) => R : void extends C ? (initialValue: I, extraArg: E) => R : (initialValue: I, extraArg: E, context: C) => R : T;
|
package/lib/hookGroup.js
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createHookManager = exports.createPlugin = exports.isPluginInstance = void 0;
|
|
4
4
|
const hooks_1 = require("./hooks");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
5
6
|
const DEFAULT_OPTIONS = {
|
|
6
7
|
name: 'untitled',
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
before: [],
|
|
9
|
+
after: [],
|
|
10
|
+
conflict: [],
|
|
10
11
|
required: [],
|
|
11
|
-
order: 0,
|
|
12
12
|
group: 0
|
|
13
13
|
};
|
|
14
14
|
const PLUGIN_SYMBOL = 'PLUGIN_SYMBOL';
|
|
@@ -16,70 +16,6 @@ const isPluginInstance = (plugin) => plugin &&
|
|
|
16
16
|
plugin.hasOwnProperty(PLUGIN_SYMBOL) &&
|
|
17
17
|
plugin.PLUGIN_SYMBOL === PLUGIN_SYMBOL;
|
|
18
18
|
exports.isPluginInstance = isPluginInstance;
|
|
19
|
-
const sortPlugins = (input) => {
|
|
20
|
-
let plugins = input.slice();
|
|
21
|
-
plugins.sort((a, b) => {
|
|
22
|
-
// sort by group first
|
|
23
|
-
if (a.group === b.group) {
|
|
24
|
-
return a.order - b.order;
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
return a.group - b.group;
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
for (let i = 0; i < plugins.length; i++) {
|
|
31
|
-
let plugin = plugins[i];
|
|
32
|
-
if (plugin.pre) {
|
|
33
|
-
for (const pre of plugin.pre) {
|
|
34
|
-
for (let j = i + 1; j < plugins.length; j++) {
|
|
35
|
-
if (plugins[j].name === pre) {
|
|
36
|
-
plugins = [
|
|
37
|
-
...plugins.slice(0, i),
|
|
38
|
-
plugins[j],
|
|
39
|
-
...plugins.slice(i, j),
|
|
40
|
-
...plugins.slice(j + 1, plugins.length)
|
|
41
|
-
];
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
if (plugin.post) {
|
|
47
|
-
for (const post of plugin.post) {
|
|
48
|
-
for (let j = 0; j < i; j++) {
|
|
49
|
-
if (plugins[j].name === post) {
|
|
50
|
-
plugins = [
|
|
51
|
-
...plugins.slice(0, j),
|
|
52
|
-
...plugins.slice(j + 1, i + 1),
|
|
53
|
-
plugins[j],
|
|
54
|
-
...plugins.slice(i + 1, plugins.length)
|
|
55
|
-
];
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return plugins;
|
|
62
|
-
};
|
|
63
|
-
const checkPlugins = (plugins) => {
|
|
64
|
-
for (const origin of plugins) {
|
|
65
|
-
if (origin.rivals) {
|
|
66
|
-
for (const rival of origin.rivals) {
|
|
67
|
-
for (const plugin of plugins) {
|
|
68
|
-
if (rival === plugin.name) {
|
|
69
|
-
throw new Error(`${origin.name} has rival ${plugin.name}`);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
if (origin.required) {
|
|
75
|
-
for (const required of origin.required) {
|
|
76
|
-
if (!plugins.some(plugin => plugin.name === required)) {
|
|
77
|
-
throw new Error(`The plugin: ${required} is required when plugin: ${origin.name} is exist.`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
19
|
function uuid() {
|
|
84
20
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
85
21
|
var r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;
|
|
@@ -141,10 +77,9 @@ const createHookManager = (hookMap, hasContext = true) => {
|
|
|
141
77
|
_plugins.push(...plugins);
|
|
142
78
|
};
|
|
143
79
|
const load = () => {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
plugins.forEach(plugin => {
|
|
80
|
+
(0, utils_1.verifyPlugins)(_plugins);
|
|
81
|
+
_plugins = (0, utils_1.sortPlugins)(_plugins);
|
|
82
|
+
_plugins.forEach(plugin => {
|
|
148
83
|
const handlers = plugin.handlers;
|
|
149
84
|
let hookName;
|
|
150
85
|
for (hookName in handlers) {
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -16,3 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./hooks"), exports);
|
|
18
18
|
__exportStar(require("./hookGroup"), exports);
|
|
19
|
+
__exportStar(require("./types"), exports);
|
package/lib/types.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { SyncHook, SyncBailHook, SyncWaterfallHook, AsyncParallelHook, AsyncSeriesWaterfallHook, SyncHookHandler, SyncBailHookHandler, SyncWaterfallHookHandler, AsyncParallelHookHandler, AsyncSeriesWaterfallHookHandler, AsyncSeriesHook, AsyncSeriesBailHook, AsyncSeriesHookHandler, AsyncSeriesBailHookHandler } from './hooks';
|
|
2
|
+
export declare type PatchPluginParameter<T, C> = RemoveManagerVoidParameter<AddContextParameter<T, C>>;
|
|
3
|
+
export declare type AddContextParameter<T, C> = T extends (initalValue: infer I, extraArg: infer E) => infer R ? (initalValue: I, extraArg: E, context: C) => R : T;
|
|
4
|
+
export declare type AnyHook = SyncHook<any, any, any> | SyncBailHook<any, any, any> | SyncWaterfallHook<any, any> | AsyncParallelHook<any, any, any> | AsyncSeriesHook<any, any, any> | AsyncSeriesBailHook<any, any, any> | AsyncSeriesWaterfallHook<any, any>;
|
|
5
|
+
export interface HookMap {
|
|
6
|
+
[x: string]: AnyHook;
|
|
7
|
+
}
|
|
8
|
+
export declare type Setup<HM extends HookMap = {}> = (utils: {
|
|
9
|
+
addHooks: (hook: Partial<HM>) => void;
|
|
10
|
+
}) => void;
|
|
11
|
+
export declare type CreatePlugin<HM extends HookMap, C> = (pluginHandlers: IPluginHandlers<HM, C> & {
|
|
12
|
+
setup?: Setup;
|
|
13
|
+
}, options?: PluginOptions) => IPluginInstance<HM, C>;
|
|
14
|
+
export declare type HookManager<HM extends HookMap, C> = {
|
|
15
|
+
createPlugin: CreatePlugin<HM, C>;
|
|
16
|
+
usePlugin: (...plugins: IPluginInstance<HM, C>[]) => void;
|
|
17
|
+
runner: RunnerType<HM>;
|
|
18
|
+
setContext: (context: C) => void;
|
|
19
|
+
clear: () => void;
|
|
20
|
+
addHooks: <EHM extends HookMap>(hook: Partial<EHM>) => void;
|
|
21
|
+
hooks: HM;
|
|
22
|
+
getPlugins: () => IPluginInstance<HM, C>[];
|
|
23
|
+
};
|
|
24
|
+
export declare type RunnerType<HM> = {
|
|
25
|
+
[K in keyof HM]: HookRunnerType<HM[K]>;
|
|
26
|
+
} & {
|
|
27
|
+
setup: Setup;
|
|
28
|
+
};
|
|
29
|
+
export declare type HookRunnerType<H> = H extends SyncHook<infer T, infer E, infer R> ? SyncHook<T, E, R>['run'] : H extends SyncBailHook<infer T, infer E, infer R> ? SyncBailHook<T, E, R>['run'] : H extends SyncWaterfallHook<infer T, infer E> ? SyncWaterfallHook<T, E>['run'] : H extends AsyncParallelHook<infer T, infer E, infer R> ? AsyncParallelHook<T, E, R>['run'] : H extends AsyncSeriesHook<infer T, infer E, infer R> ? AsyncSeriesHook<T, E, R>['run'] : H extends AsyncSeriesBailHook<infer T, infer E, infer R> ? AsyncSeriesBailHook<T, E, R>['run'] : H extends AsyncSeriesWaterfallHook<infer T, infer E> ? AsyncSeriesWaterfallHook<T, E>['run'] : never;
|
|
30
|
+
export declare type IPluginInstance<HM, C> = {
|
|
31
|
+
handlers: IPluginHandlers<HM, C>;
|
|
32
|
+
PLUGIN_SYMBOL: 'PLUGIN_SYMBOL';
|
|
33
|
+
} & Required<PluginOptions>;
|
|
34
|
+
export declare type IPluginHandlers<HM, C> = Partial<IPluginHandlersFullMap<HM, C>>;
|
|
35
|
+
export declare type IPluginHandlersFullMap<HM, C> = {
|
|
36
|
+
[K in keyof HM]: HM[K] extends SyncHook<infer T, infer E, infer R> ? PatchPluginParameter<SyncHookHandler<T, E, R>, C> : HM[K] extends SyncBailHook<infer T, infer E, infer R> ? PatchPluginParameter<SyncBailHookHandler<T, E, R>, C> : HM[K] extends SyncWaterfallHook<infer T, infer E> ? PatchPluginParameter<SyncWaterfallHookHandler<T, E>, C> : HM[K] extends AsyncParallelHook<infer T, infer E, infer R> ? PatchPluginParameter<AsyncParallelHookHandler<T, E, R>, C> : HM[K] extends AsyncSeriesHook<infer T, infer E, infer R> ? PatchPluginParameter<AsyncSeriesHookHandler<T, E, R>, C> : HM[K] extends AsyncSeriesBailHook<infer T, infer E, infer R> ? PatchPluginParameter<AsyncSeriesBailHookHandler<T, E, R>, C> : HM[K] extends AsyncSeriesWaterfallHook<infer T, infer E> ? PatchPluginParameter<AsyncSeriesWaterfallHookHandler<T, E>, C> : never;
|
|
37
|
+
};
|
|
38
|
+
export declare type PluginOptions = {
|
|
39
|
+
name?: string;
|
|
40
|
+
/** current plugin should before these configured plugins.
|
|
41
|
+
* only works for same group
|
|
42
|
+
*/
|
|
43
|
+
before?: string[];
|
|
44
|
+
/** current plugin should after these configured plugins.
|
|
45
|
+
* only works for same group.
|
|
46
|
+
*/
|
|
47
|
+
after?: string[];
|
|
48
|
+
/** current plugin should not be used with these configured plugins */
|
|
49
|
+
conflict?: string[];
|
|
50
|
+
/** current plugin should be used with these configured plugins */
|
|
51
|
+
required?: string[];
|
|
52
|
+
/** current plugin group.
|
|
53
|
+
* smaller group will be executed first
|
|
54
|
+
* 0: default
|
|
55
|
+
*/
|
|
56
|
+
group?: number;
|
|
57
|
+
[x: string]: any;
|
|
58
|
+
};
|
|
59
|
+
export declare type RemoveManagerVoidParameter<T> = T extends (initalValue: infer I, extraArg: infer E, context: infer C) => infer R ? null extends I ? null extends E ? null extends C ? (initialValue: I, extraArg: E, context: C) => R : void extends C ? (initialValue: I, extraArg: E) => R : (initialValue: I, extraArg: E, context: C) => R : void extends E ? null extends C ? (initialValue: I, context: C) => R : void extends C ? (initialValue: I) => R : (initialValue: I, context: C) => R : null extends C ? (initialValue: I, extraArg: E, context: C) => R : void extends C ? (initialValue: I, extraArg: E) => R : (initialValue: I, extraArg: E, context: C) => R : void extends I ? null extends E ? null extends C ? (extraArg: E, context: C) => R : void extends C ? (extraArg: E) => R : (extraArg: E, context: C) => R : void extends E ? null extends C ? (context: C) => R : void extends C ? () => R : (context: C) => R : null extends C ? (extraArg: E, context: C) => R : void extends C ? (extraArg: E) => R : (extraArg: E, context: C) => R : null extends E ? null extends C ? (initialValue: I, extraArg: E, context: C) => R : void extends C ? (initialValue: I, extraArg: E) => R : (initialValue: I, extraArg: E, context: C) => R : void extends E ? null extends C ? (initialValue: I, context: C) => R : void extends C ? (initialValue: I) => R : (initialValue: I, context: C) => R : null extends C ? (initialValue: I, extraArg: E, context: C) => R : void extends C ? (initialValue: I, extraArg: E) => R : (initialValue: I, extraArg: E, context: C) => R : T;
|
package/lib/types.js
ADDED
package/lib/utils.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { IPluginInstance } from './types';
|
|
2
|
+
export declare const sortPluginsByRelationShip: <T extends IPluginInstance<any, any>[]>(input: T) => T;
|
|
3
|
+
export declare const sortPlugins: <T extends IPluginInstance<any, any>[]>(input: T) => T;
|
|
4
|
+
export declare const verifyPlugins: (plugins: IPluginInstance<any, any>[]) => void;
|
package/lib/utils.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.verifyPlugins = exports.sortPlugins = exports.sortPluginsByRelationShip = void 0;
|
|
4
|
+
const sortPluginsByRelationShip = (input) => {
|
|
5
|
+
const plugins = new Map();
|
|
6
|
+
/**
|
|
7
|
+
* the key is the end point of the edge
|
|
8
|
+
* In this way, we can easily find the plugin with zero in-degree
|
|
9
|
+
*/
|
|
10
|
+
const edges = new Map();
|
|
11
|
+
const addEdge = (start, end) => {
|
|
12
|
+
if (!edges.has(end)) {
|
|
13
|
+
edges.set(end, new Set());
|
|
14
|
+
}
|
|
15
|
+
edges.get(end).add(start);
|
|
16
|
+
};
|
|
17
|
+
// Firstly, set plugins into map
|
|
18
|
+
input.forEach(plugin => {
|
|
19
|
+
plugins.set(plugin.name, plugin);
|
|
20
|
+
});
|
|
21
|
+
input.forEach(plugin => {
|
|
22
|
+
if (!edges.has(plugin.name)) {
|
|
23
|
+
edges.set(plugin.name, new Set());
|
|
24
|
+
}
|
|
25
|
+
if (plugin.before) {
|
|
26
|
+
plugin.before.forEach(name => {
|
|
27
|
+
// If the plugin is not in the input, we will ignore it
|
|
28
|
+
if (plugins.has(name)) {
|
|
29
|
+
addEdge(plugin.name, name);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (plugin.after) {
|
|
34
|
+
plugin.after.forEach(name => {
|
|
35
|
+
// If the plugin is not in the input, we will ignore it
|
|
36
|
+
if (plugins.has(name)) {
|
|
37
|
+
addEdge(name, plugin.name);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
const sorted = [];
|
|
43
|
+
while (edges.size > 0) {
|
|
44
|
+
let hasZeroInDegree = false;
|
|
45
|
+
edges.forEach((value, key) => {
|
|
46
|
+
if (value.size === 0) {
|
|
47
|
+
hasZeroInDegree = true;
|
|
48
|
+
sorted.push(plugins.get(key));
|
|
49
|
+
edges.delete(key);
|
|
50
|
+
edges.forEach(v => {
|
|
51
|
+
v.delete(key);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
if (!hasZeroInDegree) {
|
|
56
|
+
throw new Error(`Plugin circular dependency detected: ${Array.from(edges.keys()).join(', ')}. Please ensure the plugins have correct 'before' and 'after' property.`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return sorted;
|
|
60
|
+
};
|
|
61
|
+
exports.sortPluginsByRelationShip = sortPluginsByRelationShip;
|
|
62
|
+
const sortPlugins = (input) => {
|
|
63
|
+
const groupMap = new Map();
|
|
64
|
+
input.forEach(plugin => {
|
|
65
|
+
if (!groupMap.has(plugin.group)) {
|
|
66
|
+
groupMap.set(plugin.group, []);
|
|
67
|
+
}
|
|
68
|
+
groupMap.get(plugin.group).push(plugin);
|
|
69
|
+
});
|
|
70
|
+
const groupNumbers = Array.from(groupMap.keys());
|
|
71
|
+
const sortedGroupNumbers = groupNumbers.sort((a, b) => a - b);
|
|
72
|
+
const sorted = [];
|
|
73
|
+
sortedGroupNumbers.forEach(groupNumber => {
|
|
74
|
+
sorted.push(...(0, exports.sortPluginsByRelationShip)(groupMap.get(groupNumber)));
|
|
75
|
+
});
|
|
76
|
+
return sorted;
|
|
77
|
+
};
|
|
78
|
+
exports.sortPlugins = sortPlugins;
|
|
79
|
+
const verifyPlugins = (plugins) => {
|
|
80
|
+
const names = new Set();
|
|
81
|
+
for (const current of plugins) {
|
|
82
|
+
if (typeof current.name !== 'string') {
|
|
83
|
+
throw new Error(`Plugin name must be string type.`);
|
|
84
|
+
}
|
|
85
|
+
if (!current.name) {
|
|
86
|
+
throw new Error(`Plugin name must be non-empty string.`);
|
|
87
|
+
}
|
|
88
|
+
if (names.has(current.name)) {
|
|
89
|
+
throw new Error(`Plugin name duplication detected: ${current.name}.`);
|
|
90
|
+
}
|
|
91
|
+
names.add(current.name);
|
|
92
|
+
if (current.conflict) {
|
|
93
|
+
for (const conflict of current.conflict) {
|
|
94
|
+
for (const plugin of plugins) {
|
|
95
|
+
if (conflict === plugin.name) {
|
|
96
|
+
throw new Error(`Plugin conflict detected: ${current.name} has conflict with ${plugin.name}.`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (current.required) {
|
|
102
|
+
for (const required of current.required) {
|
|
103
|
+
if (!plugins.some(plugin => plugin.name === required)) {
|
|
104
|
+
throw new Error(`Plugin missing detected: ${required} is required by ${current.name}.`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
exports.verifyPlugins = verifyPlugins;
|