text: /**
   * @license
   * Copyright 2021 KonghaYao 江夏尧 <dongzhongzhidong@qq.com>
   * SPDX-License-Identifier: Apache-2.0
   */
  /* eslint-disable no-invalid-this */
  
  import { Plugin } from '@src/Pipeline/PluginSystem.js';
  import { concurrent } from '@src/utils/concurrent.js';
  
  // ! 这个 Request 文件是标准的 Plugin 的高级注册示例
  
  // Format 是边缘的处理逻辑，用于自动化相应返回数据的格式处理，与 Plugin 关系较小
  function Format(res, returnType) {
      const type = res.headers.get('content-type') || '';
      // 根据 returnType 强制返回
      if (!returnType || returnType === 'auto') {
          // 自动判断类型并解析
          if (/text|html|rtf|xml/.test(type)) {
              return res.text();
          }
          if (/json/.test(type)) {
              return res.json();
          }
          if (/arrayBuffer/.test(type)) {
              return res.arrayBuffer();
          }
          // 默认返回 Blob 数据 配合 node端 的buffer
          return res.buffer ? res.buffer() : res.blob();
      }
      if (returnType) {
          return res[returnType]();
      }
      return res.json();
  }
  
  // Plugin 的核心函数 (this.main)，用于请求
  // 第一参数为 Task 内部使用 start 事件返回的参数，你可以看成是上一个 Plugin 返回给你的数据
  // 第二个为 Plugin 内部的 options, 可以调用这些数据进行操作
  
  function request({ url, options = {} }) {
      const { returnType = 'json' } = this.options;
  
      //  获取数据为 request
      console.log('- 爬取 ', url);
      return fetch(url, Object.assign({ cache: 'force-cache' }, options))
          .then((res) => {
              if (!res.ok) {
                  throw Error(res.statusText);
              }
              return Format(res, returnType);
          })
          .then((res) => {
              console.log(`${url} 爬取成功`);
              return res;
          })
          .catch((err) => {
              throw err;
          });
  }
  
  // 在超过重试次数时，进行的操作
  function HandleError(err) {
      throw err;
  }
  export function Request(options = {}) {
      return Plugin({
          init() {}, // 在所有工作开始前会启动的函数，可以用于 Promise 加载一些 js 插件
          name: 'Request', // 这个 name 是负责进行监控的标志符号
          main: request, // 功能性的核心函数
          options, // 接收所有的参数，提供给所有函数使用
  
          operator() {
              // 复写 operator 函数，属于高级操作，可以操作到最顶层的数据流环节
  
              // 通过 this.options 来获取传入的参数，这个参数解析都是由 Plugin 开发者来设置逻辑的
              // 所以灵活性很高
              const { delay = 200, buffer = 1, retry = 3, handleError = null } = this.options;
  
              return ($source) =>
                  $source.pipe(
                      concurrent(
                          (task) =>
                              // 注意此处的 TaskStarter 是 Plugin 内置的函数，
                              // 通过这个函数可以直接回应 Task
                              // 使得 Plugin 开发者 不用学 Task 相关知识，
                              // 而只是调用一下这个形式就可以了
                              // TaskStarter 是用于间接调用 main 函数的 Wrapper 函数，
                              // 主要是对 Task 进行一些操作
                              this.TaskStarter(task),
                          {
                              delay,
                              buffer,
                              retry,
                              handleError: handleError || HandleError,
                          },
                      ),
                  );
          },
      });
  }
  