Repository: artusjs/core
Pull request #134 (2022-07-12 13:21:01)

refactor(scanner): modify exclude option for plugin & excluded rename
related #129 
改动点如下：
- BREAKING! Scanner 中所有 `excluded` 均调整为 `exclude`
- `Scanner.formatWalkOptions` 补充逻辑： `exclude` 使用默认常量序列 + 插件 Meta 中声明的 exclude 值（未声明为空）

对于 #129 实现中的其他部分：
- extensions 目前看不涉及单独配置，暂不考虑支持
- Framework 中目前未包括对 Metadata 的处理（不要求 meta.yaml），此处需要评估是否有必要增加，或在其他位置声明 exclude/configDir（如 package.json）cc @hyj1991 

cc @hyj1991  @JerrysShan @wengeezhang 

hyj1991: `meta.yml` 其实没必要强制吧，framework 和 plugin 不一样，它不需要 name，pluin 是因为至少要有一个 name 才必须检测 `meta.yml` 的
hyj1991: 其实这些非标的文件，会给后面 ts 构建到 js 发包带来一些麻烦，这个还没想好怎么统一处理掉
noahziheng: 单测已补充

@hyj1991 Framework 的 Meta 后面专门处理一下吧，有关这几个非标文件的处理我有个想法，晚点整理个 RFC

Patch:
diff --git a/package.json b/package.json
index a9eb320..b709b48 100644
--- a/package.json
+++ b/package.json
@@ -46,6 +46,7 @@
   "devDependencies": {
     "@artus/eslint-config-artus": "0.0.1",
     "@artus/tsconfig": "0.0.1",
+    "@babel/core": "^7.18.6",
     "@types/jest": "^27.4.1",
     "@types/js-yaml": "^4.0.5",
     "@types/koa": "^2.13.4",
diff --git a/src/plugin/types.ts b/src/plugin/types.ts
index aeef934..dbc782e 100644
--- a/src/plugin/types.ts
+++ b/src/plugin/types.ts
@@ -8,6 +8,7 @@ export interface PluginMetadata {
   dependencies?: PluginDependencyItem[];
   type?: PluginType;
   configDir?: string
+  exclude?: string[];
 }
 
 export interface PluginDependencyItem {
diff --git a/src/scanner/scan.ts b/src/scanner/scan.ts
index 97f6e7d..5c4d4e1 100644
--- a/src/scanner/scan.ts
+++ b/src/scanner/scan.ts
@@ -16,6 +16,7 @@ import ConfigurationHandler, { ConfigObject } from '../configuration';
 import { FrameworkConfig, FrameworkHandler } from '../framework';
 import { BasePlugin, PluginFactory } from '../plugin';
 import { ScanUtils } from './utils';
+import { PluginMetadata } from '../plugin/types';
 
 export class Scanner {
   private moduleExtensions = ['.js', '.json', '.node'];
@@ -32,7 +33,7 @@ export class Scanner {
       configDir: DEFAULT_CONFIG_DIR,
       loaderListGenerator: (defaultLoaderList: string[]) => defaultLoaderList,
       ...options,
-      excluded: DEFAULT_EXCLUDES.concat(options.excluded ?? []),
+      exclude: DEFAULT_EXCLUDES.concat(options.exclude ?? []),
       extensions: [...new Set(this.moduleExtensions.concat(options.extensions ?? [], ['.yaml']))],
     };
   }
@@ -110,7 +111,7 @@ export class Scanner {
       this.setPluginMeta(plugin);
       await this.walk(
         plugin.importPath,
-        this.formatWalkOptions('plugin', plugin.importPath, plugin.name, plugin.metadata.configDir),
+        this.formatWalkOptions('plugin', plugin.importPath, plugin.name, plugin.metadata),
       );
     }
 
@@ -152,7 +153,7 @@ export class Scanner {
     const loaderFactory = LoaderFactory.create(container);
     const configItemList: (ManifestItem|null)[] = await Promise.all(configFileList.map(async filename => {
       const extname = path.extname(filename);
-      if (ScanUtils.isExclude(filename, extname, this.options.excluded, this.options.extensions)) {
+      if (ScanUtils.isExclude(filename, extname, this.options.exclude, this.options.extensions)) {
         return null;
       }
       let loader = await loaderFactory.findLoaderName({
@@ -216,22 +217,24 @@ export class Scanner {
     return frameworkDirs;
   }
 
-  private formatWalkOptions(source: string, baseDir: string, unitName?: string, configDir?: string): WalkOptions {
-    const commonOptions = {
-      extensions: this.options.extensions,
-      excluded: this.options.excluded,
+  private formatWalkOptions(source: string, baseDir: string, unitName?: string, metaInfo?: Partial<PluginMetadata>): WalkOptions {
+    const opts: WalkOptions = {
       itemMap: this.itemMap,
+      source,
+      baseDir,
+      unitName: unitName ?? baseDir,
+      extensions: this.options.extensions,
+      exclude: this.options.exclude,
+      configDir: this.options.configDir,
     };
 
-    unitName ??= baseDir;
-    configDir ??= this.options.configDir;
+    if (source === 'plugin') {
+      // TODO: Only support plugin meta now, need cover framework meta later
+      opts.exclude = DEFAULT_EXCLUDES.concat(metaInfo.exclude ?? []);
+      opts.configDir = metaInfo.configDir ?? this.options.configDir;
+    }
 
-    return Object.assign({}, commonOptions, {
-      source,
-      baseDir,
-      unitName,
-      configDir,
-    });
+    return opts;
   }
 
   private getItemsFromMap(relative: boolean, appRoot: string): ManifestItem[] {
diff --git a/src/scanner/types.ts b/src/scanner/types.ts
index 38df515..a16247b 100644
--- a/src/scanner/types.ts
+++ b/src/scanner/types.ts
@@ -5,7 +5,7 @@ export interface ScannerOptions {
   extensions: string[];
   needWriteFile: boolean;
   useRelativePath: boolean;
-  excluded: string[];
+  exclude: string[];
   configDir: string;
   envs?: string[];
   loaderListGenerator: (defaultLoaderList: string[]) => (string | typeof BaseLoader)[];
@@ -16,7 +16,7 @@ export interface WalkOptions {
   baseDir: string;
   configDir: string;
   extensions: string[];
-  excluded: string[];
+  exclude: string[];
   itemMap: Map<string, ManifestItem[]>;
   unitName?: string;
 }
diff --git a/src/scanner/utils.ts b/src/scanner/utils.ts
index 5cdbc66..1049868 100644
--- a/src/scanner/utils.ts
+++ b/src/scanner/utils.ts
@@ -32,7 +32,7 @@ export class ScanUtils {
     for (const item of items) {
       const realPath = path.resolve(root, item);
       const extname = path.extname(realPath);
-      if (this.isExclude(item, extname, options.excluded, options.extensions)) {
+      if (this.isExclude(item, extname, options.exclude, options.extensions)) {
         continue;
       }
       const itemStat = await fs.stat(realPath);
@@ -78,10 +78,10 @@ export class ScanUtils {
   }
 
   static isExclude(filename: string, extname: string,
-    excluded: string[], extensions: string[]): boolean {
+    exclude: string[], extensions: string[]): boolean {
     let result = false;
-    if (!result && excluded) {
-      result = isMatch(filename, excluded);
+    if (!result && exclude) {
+      result = isMatch(filename, exclude);
     }
 
     if (!result && extname) {


Test patch:
diff --git a/test/fixtures/app_koa_with_ts/src/redis_plugin/meta.yaml b/test/fixtures/app_koa_with_ts/src/redis_plugin/meta.yaml
index 8a1d960..78bdbac 100644
--- a/test/fixtures/app_koa_with_ts/src/redis_plugin/meta.yaml
+++ b/test/fixtures/app_koa_with_ts/src/redis_plugin/meta.yaml
@@ -1,1 +1,4 @@
 name: redis
+exclude:
+  - not_to_be_scanned_dir
+  - not_to_be_scanned_file.ts
diff --git a/test/fixtures/app_koa_with_ts/src/redis_plugin/not_to_be_scanned_dir/not_to_be_scanned_file.ts b/test/fixtures/app_koa_with_ts/src/redis_plugin/not_to_be_scanned_dir/not_to_be_scanned_file.ts
new file mode 100644
index 0000000..cd736b3
--- /dev/null
+++ b/test/fixtures/app_koa_with_ts/src/redis_plugin/not_to_be_scanned_dir/not_to_be_scanned_file.ts
@@ -0,0 +1,1 @@
+export default class DummyClazz {}
diff --git a/test/fixtures/app_koa_with_ts/src/redis_plugin/not_to_be_scanned_file.ts b/test/fixtures/app_koa_with_ts/src/redis_plugin/not_to_be_scanned_file.ts
new file mode 100644
index 0000000..cd736b3
--- /dev/null
+++ b/test/fixtures/app_koa_with_ts/src/redis_plugin/not_to_be_scanned_file.ts
@@ -0,0 +1,1 @@
+export default class DummyClazz {}
diff --git a/test/scanner.test.ts b/test/scanner.test.ts
index 679756a..dbdcb2d 100644
--- a/test/scanner.test.ts
+++ b/test/scanner.test.ts
@@ -14,6 +14,8 @@ describe('test/scanner.test.ts', () => {
     // console.log('manifest', manifest);
     expect(manifest.items.length).toBe(11);
 
+    expect(manifest.items.find(item => item.filename === 'not_to_be_scanned_file.ts')).toBeFalsy();
+
     expect(manifest.items.filter(item => item.loader === 'plugin-config').length).toBe(0);
     expect(manifest.items.filter(item => item.loader === 'plugin-meta').length).toBe(1);
     expect(manifest.items.filter(item => item.loader === 'exception').length).toBe(1);