1/* 2 * Copyright (c) 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { isNumber } from './safe-types'; 17import { Plugins, PluginContext, PluginHandler, PluginState, PluginExecutor } from '../../common/plugin-context'; 18import * as arkts from '@koalaui/libarkts'; 19 20export interface PluginDriver { 21 initPlugins(plugins: Plugins[]): void; 22 getSortedPlugins(state: arkts.Es2pandaContextState): PluginExecutor[] | undefined; 23 getPluginContext(): PluginContext; 24} 25 26function toCamelCase(str: string): string { 27 return str 28 .split('_') 29 .map((word, index) => { 30 if (index === 0) { 31 return word; 32 } 33 return word.charAt(0).toUpperCase() + word.slice(1); 34 }) 35 .join(''); 36} 37 38function stateName(value: arkts.Es2pandaContextState): PluginState { 39 return toCamelCase( 40 arkts.Es2pandaContextState[value].substring('ES2PANDA_STATE_'.length).toLowerCase() 41 ) as PluginState; 42} 43 44function selectPlugins(plugins: Plugins[], stage: PluginState): PluginExecutor[] { 45 const pre: PluginExecutor[] = []; 46 const normal: PluginExecutor[] = []; 47 const post: PluginExecutor[] = []; 48 49 plugins 50 .filter((it) => stage in it) 51 .forEach((it) => { 52 const pluginName: string = it.name; 53 const handler: PluginHandler = it[stage]!; 54 const order: string | undefined = typeof handler === 'object' ? handler.order : undefined; 55 const rawPluginHook: PluginExecutor = { 56 name: pluginName, 57 handler: typeof handler === 'object' ? handler.handler : handler, 58 }; 59 60 if (order === 'pre') { 61 pre.push(rawPluginHook); 62 } else if (order === 'post') { 63 post.push(rawPluginHook); 64 } else { 65 normal.push(rawPluginHook); 66 } 67 }); 68 69 return [...pre, ...normal, ...post]; 70} 71 72class MockPluginDriver implements PluginDriver { 73 private sortedPlugins: Map<arkts.Es2pandaContextState, PluginExecutor[] | undefined>; 74 private context: PluginContext; 75 76 constructor() { 77 this.sortedPlugins = new Map<arkts.Es2pandaContextState, PluginExecutor[] | undefined>(); 78 this.context = new PluginContext(); 79 } 80 81 public initPlugins(plugins: Plugins[]): void { 82 const pluginsByState = new Map<arkts.Es2pandaContextState, PluginExecutor[] | undefined>(); 83 84 Object.values(arkts.Es2pandaContextState) 85 .filter(isNumber) 86 .forEach((it) => { 87 const selected = selectPlugins(plugins, stateName(it)); 88 if (selected.length > 0) { 89 pluginsByState.set(it, selected); 90 } else { 91 pluginsByState.set(it, undefined); 92 } 93 }); 94 95 this.sortedPlugins = pluginsByState; 96 } 97 98 public getSortedPlugins(state: arkts.Es2pandaContextState): PluginExecutor[] | undefined { 99 return this.sortedPlugins.get(state); 100 } 101 102 public getPluginContext(): PluginContext { 103 return this.context; 104 } 105} 106 107export { stateName, MockPluginDriver }; 108