<commit_before>/**
 * @since 2016-11-16 10:20
 * @author vivaxy
 */

import path from 'path';
import execa from 'execa';
import Listr from 'listr';
import fse from 'fs-extra';
import chalk from 'chalk';
import figures from 'figures';
import inquirer from 'inquirer';
import gitUsername from 'git-user-name';

import fileExists from '../file/fileExists';
import directoryExists from '../file/directoryExists';
import isDirectoryEmpty from '../file/isDirectoryEmpty';
import * as configManager from '../lib/configManager';
import updateScaffoldStat from '../lib/updateScaffoldStat';
import checkGitRepository from '../git/checkGitRepository';
import checkGitClean from '../git/getClean';
import getGitRemoteURL from '../git/getRemoteURL';
import getCommitHash from '../git/getCommitHash';
import { GT_HOME, MODULES_FOLDER, GIT_FOLDER, PROJECT_GT_FILE } from '../config';

import getCopyFiles from '../presets/copyFiles';
import getWriteFile from '../presets/writeFile';
import getUpdateFile from '../presets/updateFile';
import getUpdateFiles from '../presets/updateFiles';
import getWriteJson from '../presets/writeJson';
import getUpdateJson from '../presets/updateJson';
import getRemoveFiles from '../presets/removeFiles';
import getAddScaffoldInfo from '../presets/addScaffoldInfo';

const cwd = process.cwd();

const gitCloneTask = async({ selectedScaffoldRepo, selectedScaffoldFolder }) => {
    const [repoURL, commitIsh] = selectedScaffoldRepo.split('#');
    const clone = await execa('git', ['clone', repoURL, selectedScaffoldFolder]);
    if (clone.code !== 0) {
        throw new Error(`clone error:
selectedScaffoldRepo: ${selectedScaffoldRepo}
repoURL: ${repoURL}
${clone.stderr}`);
    }
    process.chdir(selectedScaffoldFolder);
    if (commitIsh) {
        await execa('git', ['checkout', commitIsh]);
        if (clone.code !== 0) {
            throw new Error(`checkout error:
selectedScaffoldRepo: ${selectedScaffoldRepo}
commitIsh: ${commitIsh}
${clone.stderr}`);
        }
    }
    process.chdir(cwd);
};

const gitPullTask = async({ selectedScaffoldFolder }) => {
    process.chdir(selectedScaffoldFolder);
    const gitClean = await checkGitClean();
    if (!gitClean) {
        await execa('git', ['checkout', '.']);
    }
    await execa('git', ['pull']);
    process.chdir(cwd);
};

const npmInstallTask = async({ selectedScaffoldFolder }) => {
    process.chdir(selectedScaffoldFolder);
    const yarnLockExists = await fileExists(path.join(selectedScaffoldFolder, 'yarn.lock'));
    if (yarnLockExists) {
        await execa('yarn', ['install']);
    } else {
        await execa('npm', ['install']);
    }
    process.chdir(cwd);
};

const prepareForCopyProjectFiles = async(ctx) => {
    const { selectedScaffoldFolder } = ctx;
    const copyInfo = {
        project: { folder: cwd },
        scaffold: { folder: selectedScaffoldFolder },
    };
    const copyFiles = getCopyFiles(copyInfo);
    const files = await fse.readdir(selectedScaffoldFolder);
    const excludeGitFiles = files.filter((file) => {
        return file !== GIT_FOLDER && file !== MODULES_FOLDER;
    });
    copyFiles(excludeGitFiles);
};

const prepareForScaffoldGT = async(ctx) => {
    const { selectedScaffoldName, selectedScaffoldFolder, projectGTFilePath } = ctx;

    const projectGT = require(projectGTFilePath); // eslint-disable-line global-require, import/no-dynamic-require
    let projectGit = null;

    const isGitRepository = await checkGitRepository();
    if (isGitRepository) {
        const repositoryURL = await getGitRemoteURL();
        projectGit = { repositoryURL, username: gitUsername() };
    }

    process.chdir(selectedScaffoldFolder);
    const headHash = await getCommitHash();
    process.chdir(cwd);

    const GTInfo = {
        project: { folder: cwd, name: cwd.split(path.sep).pop(), git: projectGit },
        scaffold: { folder: selectedScaffoldFolder, name: selectedScaffoldName, git: { headHash } },
    };

    GTInfo.presets = {
        copyFiles: getCopyFiles(GTInfo),
        writeFile: getWriteFile(GTInfo),
        updateFile: getUpdateFile(GTInfo),
        writeJson: getWriteJson(GTInfo),
        updateJson: getUpdateJson(GTInfo),
        removeFiles: getRemoveFiles(GTInfo),
        updateFiles: getUpdateFiles(GTInfo),
        addScaffoldInfo: getAddScaffoldInfo(GTInfo),
    };

    ctx.projectGT = projectGT; // eslint-disable-line no-param-reassign
    ctx.GTInfo = GTInfo; // eslint-disable-line no-param-reassign
};

const runScaffoldGT = async({ projectGT, GTInfo }) => {
    return await projectGT.init(GTInfo);
};

const updateStat = async({ selectedScaffoldName }) => {
    await updateScaffoldStat(selectedScaffoldName);
};

const getFriendlyInformation = (ex) => {
    if (ex.message === 'spawn yarn ENOENT') {
        return `Please install \`yarn\`.
See [docs](https://yarnpkg.com/en/docs/install) for details.`;
    }
};

let projectGTFileExists = false;

export const command = 'init';
export const describe = 'Choose a scaffold to init your new project';
export const builder = {};
export const handler = async() => {
    // check dir empty?
    const isCurrentDirectoryEmpty = await isDirectoryEmpty(cwd, ['.git']);
    if (!isCurrentDirectoryEmpty) {
        const continueResult = await inquirer.prompt([
            {
                type: 'confirm',
                name: 'continue',
                message: 'Current directory is not empty, files will be overridden. Continue?',
                default: true,
            },
        ]);
        if (!continueResult.continue) {
            return;
        }
    }

    const userConfig = configManager.read();
    const scaffoldConfig = userConfig.scaffold;
    const scaffoldNameList = configManager.readScaffoldListByStatOrder();

    const answer = await inquirer.prompt([
        {
            type: 'list',
            name: 'scaffold',
            message: 'Choose a scaffold...',
            choices: scaffoldNameList,
        },
    ]);

    const selectedScaffoldName = answer.scaffold;
    const selectedScaffoldRepo = scaffoldConfig[selectedScaffoldName].repo;
    const selectedScaffoldFolder = path.join(GT_HOME, selectedScaffoldName);

    const projectGTFilePath = path.join(GT_HOME, selectedScaffoldName, PROJECT_GT_FILE);

    const gitTasks = [
        {
            title: 'Clone scaffold.',
            task: gitCloneTask,
            skip: async() => {
                const selectedScaffoldFolderExists = await directoryExists(selectedScaffoldFolder);
                if (selectedScaffoldFolderExists) {
                    return 'scaffold exists';
                }
            },
        },
        { title: 'Pull scaffold.', task: gitPullTask },
    ];

    const preTasks = [];
    const postTasks = [{ title: 'Finishing.', task: updateStat }];

    const gitListr = new Listr(gitTasks);

    let listrContext = { selectedScaffoldName, selectedScaffoldRepo, selectedScaffoldFolder, projectGTFilePath };

    try {
        listrContext = await gitListr.run(listrContext);

        projectGTFileExists = await fileExists(projectGTFilePath);

        if (projectGTFileExists) {
            preTasks.push(
                { title: 'Install scaffold npm packages.', task: npmInstallTask },
                { title: 'Prepare for scaffold GT.', task: prepareForScaffoldGT },
            );
            postTasks.unshift({ title: 'Run scaffold GT.', task: runScaffoldGT });
        } else {
            preTasks.push({ title: 'Prepare for copy project files.', task: prepareForCopyProjectFiles });
        }

        const preListr = new Listr(preTasks);
        const postListr = new Listr(postTasks);

        listrContext = await preListr.run(listrContext);
        if (listrContext.GTInfo) {
            listrContext.GTInfo.config = {};
        }

        if (listrContext.projectGT && listrContext.projectGT.ask) {
            listrContext.GTInfo.config = await listrContext.projectGT.ask(listrContext.GTInfo);
        }

        listrContext = await postListr.run(listrContext);

        if (listrContext.projectGT && listrContext.projectGT.after) {
            await listrContext.projectGT.after(listrContext.GTInfo);
        }
    } catch (ex) {
        console.log(ex);
        console.log(`${chalk.blue(figures('ℹ'))} ${getFriendlyInformation(ex)}`);
    }
};
<commit_msg>style(init): :lipstick:Optimize error handling<commit_after>/**
 * @since 2016-11-16 10:20
 * @author vivaxy
 */

import path from 'path';
import execa from 'execa';
import Listr from 'listr';
import fse from 'fs-extra';
import chalk from 'chalk';
import figures from 'figures';
import inquirer from 'inquirer';
import gitUsername from 'git-user-name';

import fileExists from '../file/fileExists';
import directoryExists from '../file/directoryExists';
import isDirectoryEmpty from '../file/isDirectoryEmpty';
import * as configManager from '../lib/configManager';
import updateScaffoldStat from '../lib/updateScaffoldStat';
import checkGitRepository from '../git/checkGitRepository';
import checkGitClean from '../git/getClean';
import getGitRemoteURL from '../git/getRemoteURL';
import getCommitHash from '../git/getCommitHash';
import { GT_HOME, MODULES_FOLDER, GIT_FOLDER, PROJECT_GT_FILE } from '../config';

import getCopyFiles from '../presets/copyFiles';
import getWriteFile from '../presets/writeFile';
import getUpdateFile from '../presets/updateFile';
import getUpdateFiles from '../presets/updateFiles';
import getWriteJson from '../presets/writeJson';
import getUpdateJson from '../presets/updateJson';
import getRemoveFiles from '../presets/removeFiles';
import getAddScaffoldInfo from '../presets/addScaffoldInfo';

const cwd = process.cwd();

const gitCloneTask = async({ selectedScaffoldRepo, selectedScaffoldFolder }) => {
    const [repoURL, commitIsh] = selectedScaffoldRepo.split('#');
    const clone = await execa('git', ['clone', repoURL, selectedScaffoldFolder]);
    if (clone.code !== 0) {
        throw new Error(`clone error:
selectedScaffoldRepo: ${selectedScaffoldRepo}
repoURL: ${repoURL}
${clone.stderr}`);
    }
    process.chdir(selectedScaffoldFolder);
    if (commitIsh) {
        await execa('git', ['checkout', commitIsh]);
        if (clone.code !== 0) {
            throw new Error(`checkout error:
selectedScaffoldRepo: ${selectedScaffoldRepo}
commitIsh: ${commitIsh}
${clone.stderr}`);
        }
    }
    process.chdir(cwd);
};

const gitPullTask = async({ selectedScaffoldFolder }) => {
    process.chdir(selectedScaffoldFolder);
    const gitClean = await checkGitClean();
    if (!gitClean) {
        await execa('git', ['checkout', '.']);
    }
    await execa('git', ['pull']);
    process.chdir(cwd);
};

const npmInstallTask = async({ selectedScaffoldFolder }) => {
    process.chdir(selectedScaffoldFolder);
    const yarnLockExists = await fileExists(path.join(selectedScaffoldFolder, 'yarn.lock'));
    if (yarnLockExists) {
        await execa('yarn', ['install']);
    } else {
        await execa('npm', ['install']);
    }
    process.chdir(cwd);
};

const prepareForCopyProjectFiles = async(ctx) => {
    const { selectedScaffoldFolder } = ctx;
    const copyInfo = {
        project: { folder: cwd },
        scaffold: { folder: selectedScaffoldFolder },
    };
    const copyFiles = getCopyFiles(copyInfo);
    const files = await fse.readdir(selectedScaffoldFolder);
    const excludeGitFiles = files.filter((file) => {
        return file !== GIT_FOLDER && file !== MODULES_FOLDER;
    });
    copyFiles(excludeGitFiles);
};

const prepareForScaffoldGT = async(ctx) => {
    const { selectedScaffoldName, selectedScaffoldFolder, projectGTFilePath } = ctx;

    const projectGT = require(projectGTFilePath); // eslint-disable-line global-require, import/no-dynamic-require
    let projectGit = null;

    const isGitRepository = await checkGitRepository();
    if (isGitRepository) {
        const repositoryURL = await getGitRemoteURL();
        projectGit = { repositoryURL, username: gitUsername() };
    }

    process.chdir(selectedScaffoldFolder);
    const headHash = await getCommitHash();
    process.chdir(cwd);

    const GTInfo = {
        project: { folder: cwd, name: cwd.split(path.sep).pop(), git: projectGit },
        scaffold: { folder: selectedScaffoldFolder, name: selectedScaffoldName, git: { headHash } },
    };

    GTInfo.presets = {
        copyFiles: getCopyFiles(GTInfo),
        writeFile: getWriteFile(GTInfo),
        updateFile: getUpdateFile(GTInfo),
        writeJson: getWriteJson(GTInfo),
        updateJson: getUpdateJson(GTInfo),
        removeFiles: getRemoveFiles(GTInfo),
        updateFiles: getUpdateFiles(GTInfo),
        addScaffoldInfo: getAddScaffoldInfo(GTInfo),
    };

    ctx.projectGT = projectGT; // eslint-disable-line no-param-reassign
    ctx.GTInfo = GTInfo; // eslint-disable-line no-param-reassign
};

const runScaffoldGT = async({ projectGT, GTInfo }) => {
    return await projectGT.init(GTInfo);
};

const updateStat = async({ selectedScaffoldName }) => {
    await updateScaffoldStat(selectedScaffoldName);
};

const getFriendlyInformation = (ex) => {
    if (ex.message === 'spawn yarn ENOENT') {
        return `Please install \`yarn\`.
See [docs](https://yarnpkg.com/en/docs/install) for details.`;
    }
    return 'Please file an issue on [Github](https://github.com/vivaxy/granturismo/issues) with error details.';
};

let projectGTFileExists = false;

export const command = 'init';
export const describe = 'Choose a scaffold to init your new project';
export const builder = {};
export const handler = async() => {
    // check dir empty?
    const isCurrentDirectoryEmpty = await isDirectoryEmpty(cwd, ['.git']);
    if (!isCurrentDirectoryEmpty) {
        const continueResult = await inquirer.prompt([
            {
                type: 'confirm',
                name: 'continue',
                message: 'Current directory is not empty, files will be overridden. Continue?',
                default: true,
            },
        ]);
        if (!continueResult.continue) {
            return;
        }
    }

    const userConfig = configManager.read();
    const scaffoldConfig = userConfig.scaffold;
    const scaffoldNameList = configManager.readScaffoldListByStatOrder();

    const answer = await inquirer.prompt([
        {
            type: 'list',
            name: 'scaffold',
            message: 'Choose a scaffold...',
            choices: scaffoldNameList,
        },
    ]);

    const selectedScaffoldName = answer.scaffold;
    const selectedScaffoldRepo = scaffoldConfig[selectedScaffoldName].repo;
    const selectedScaffoldFolder = path.join(GT_HOME, selectedScaffoldName);

    const projectGTFilePath = path.join(GT_HOME, selectedScaffoldName, PROJECT_GT_FILE);

    const gitTasks = [
        {
            title: 'Clone scaffold.',
            task: gitCloneTask,
            skip: async() => {
                const selectedScaffoldFolderExists = await directoryExists(selectedScaffoldFolder);
                if (selectedScaffoldFolderExists) {
                    return 'scaffold exists';
                }
            },
        },
        { title: 'Pull scaffold.', task: gitPullTask },
    ];

    const preTasks = [];
    const postTasks = [{ title: 'Finishing.', task: updateStat }];

    const gitListr = new Listr(gitTasks);

    let listrContext = { selectedScaffoldName, selectedScaffoldRepo, selectedScaffoldFolder, projectGTFilePath };

    try {
        listrContext = await gitListr.run(listrContext);

        projectGTFileExists = await fileExists(projectGTFilePath);

        if (projectGTFileExists) {
            preTasks.push(
                { title: 'Install scaffold npm packages.', task: npmInstallTask },
                { title: 'Prepare for scaffold GT.', task: prepareForScaffoldGT },
            );
            postTasks.unshift({ title: 'Run scaffold GT.', task: runScaffoldGT });
        } else {
            preTasks.push({ title: 'Prepare for copy project files.', task: prepareForCopyProjectFiles });
        }

        const preListr = new Listr(preTasks);
        const postListr = new Listr(postTasks);

        listrContext = await preListr.run(listrContext);
        if (listrContext.GTInfo) {
            listrContext.GTInfo.config = {};
        }

        if (listrContext.projectGT && listrContext.projectGT.ask) {
            listrContext.GTInfo.config = await listrContext.projectGT.ask(listrContext.GTInfo);
        }

        listrContext = await postListr.run(listrContext);

        if (listrContext.projectGT && listrContext.projectGT.after) {
            await listrContext.projectGT.after(listrContext.GTInfo);
        }
    } catch (ex) {
        console.log(ex);
        console.log(`\n${chalk.blue(figures('ℹ'))} ${getFriendlyInformation(ex)}`);
    }
};
<|endoftext|>


<commit_before>const karma = require("karma");
const Server = karma.Server;
const runner = karma.runner;
const karmaConfig = require("../config/karma-config").default;
const spawn = require("cross-spawn").spawn;
const path = require("path");
const CWD = process.cwd();
const chokidar = require("chokidar");
const logger = require("../lib/cliLogger");

const NODE_MODULES_PATH = path.join(__dirname, "..", "..", "node_modules");
const MOCHA_PATH = path.join(NODE_MODULES_PATH, ".bin", "mocha");
const MOCHA_COVERAGE_PATH = path.join(NODE_MODULES_PATH, ".bin", "_mocha");
const MOCHA_TEST_PATH = `${CWD}/test/**/*.test.js`;
const MOCHA_HELPER_PATH = path.join(__dirname, "..", "lib", "testHelperMocha.js");
const BABEL_NODE_PATH = path.join(NODE_MODULES_PATH, ".bin", "babel-node");
const BABEL_ISTANBUL_PATH = path.join(NODE_MODULES_PATH, "babel-istanbul", "lib", "cli.js");
const INSPECTOR_PATH = path.join(NODE_MODULES_PATH, ".bin", "node-inspector");
const MOCHA_ENV = { ...process.env, ...{ NODE_PATH: CWD, NODE_ENV: "test" }};

function watchSources(callback) {
  // Debounce file watches
  let timeout;
  chokidar.watch([path.join(CWD, "src/**/*.js"), path.join(CWD, "test/**/*.js")], {
    ignored: /[\/\\]\./,
    persistent: true
  }).on("all", function() {
    clearTimeout(timeout);
    timeout = setTimeout(() => {
      callback();
    }, 250);
  });
}

function createMochaArgs(options, coverage) {
  const args = ["--require", MOCHA_HELPER_PATH];
  if (!coverage) {
    args.push("--reporter");
    args.push(options.reporter ? options.reporter : "dot");
  }
  args.push(MOCHA_TEST_PATH);
  if (options.debugTest) {
    args.push("--debug");
  }
  if (!options.single && !options.debugTest) {
    args.push("--watch");
  }
  return args;
}

/*
 * Run Mocha tests, handled differently with different options.
 *
 * @param {object} options            Command-line options in Commander format.
 * @param {string} options.reporter   Mocha reporter to use, ex. 'dot' or 'min'
 * @param {bool}   options.debugTest  Run test in debug mode. Assumes watch: false.
 * @param {bool}   options.single     Run once (watch: false).
 * @returns {object}                  Resulting process from spawn().
 *
 */
function useMocha(options) {
  const spawnOpts = {
    mocha: [
      MOCHA_PATH,
      createMochaArgs(options, false),
      {
        stdio: "inherit",
        env: MOCHA_ENV
      }
    ],
    coverage: [
      BABEL_NODE_PATH,
      [
        BABEL_ISTANBUL_PATH,
        "cover",
        "--include-all-sources",
        "--root",
        "src",
        "--report",
        "html",
        "--dir",
        "coverage/html",
        MOCHA_COVERAGE_PATH,
        ...createMochaArgs(options, true)
      ],
      {
        // Suppress error output since it includes the entire test run!
        stdio: "ignore",
        env: MOCHA_ENV
      }
    ],
    single: [
      BABEL_NODE_PATH,
      [
        BABEL_ISTANBUL_PATH,
        "cover",
        "--include-all-sources",
        "--root",
        "src",
        "--report",
        "cobertura",
        "--dir",
        "coverage/xml",
        MOCHA_COVERAGE_PATH,
        ...createMochaArgs(options, true)
      ],
      {
        stdio: "inherit",
        env: MOCHA_ENV
      }
    ]
  };

  if (options.debugTest) {
    debug();
  } else if (options.single) {
    spawn(...spawnOpts.single).on("exit", function(exitCode) {
      process.exit(exitCode);
    });
  } else {
    watch();
  }

  function debug() {
    // Start up the inspector and open it in a browser window.
    spawn(INSPECTOR_PATH, [], { stdio: "inherit" });
    spawn("open", ["http://127.0.0.1:8080/debug?port=5858"], { stdio: "inherit" });

    // Node segfaults when using debug with Mocha's built-in watch. Booooo!
    // Instead, we'll use Chokidar to watch - it's slower since it rebuilds each time, but it works, and isn't too
    // bad since debugging tests is expected to be a slower process than "save/see results".
    let running = false;
    watchSources(function() {
      if (running) {
        return;
      }
      running = true;
      const child = spawn(...spawnOpts.mocha);

      child.on("exit", function() {
        running = false;
      });
    });
  }

  function watch() {
    // If not debugging, start up mocha in watch mode.
    spawn(...spawnOpts.mocha);

    // Set up a watcher to create coverage reports in the background, only messaging on success/failure.
    // To ensure only the latest version is available, kill/restart the process on each change.
    let child;
    watchSources(function() {
      if (child) {
        child.kill();
      }
      child = spawn(...spawnOpts.coverage);
      child.on("exit", function(exitCode) {
        if (exitCode === 0) {
          logger.success("Coverage report generated.");
        } else if (exitCode === 1) {
          logger.error("Coverage report generated, but with test errors.");
        }
      });
    });
  }
}

function useKarma(options) {
  // override browser setting to use firefox instead of Chrome if specified
  if (options.firefox) {
    karmaConfig.browsers = ["Firefox"];
  }

  if (options.single) {
    karmaConfig.singleRun = options.single;
  }

  const server = new Server(karmaConfig);

  server.start();
  server.on("browsers_ready", function () {
    runner.run(karmaConfig, () => {});
  });
}

module.exports = function(options) {
  // override to run tests in Node without Karma/Webpack
  if (options.karma) {
    useKarma(options);
  } else {
    useMocha(options);
  }
};
<commit_msg>Change reporting to lcov.<commit_after>const karma = require("karma");
const Server = karma.Server;
const runner = karma.runner;
const karmaConfig = require("../config/karma-config").default;
const spawn = require("cross-spawn").spawn;
const path = require("path");
const CWD = process.cwd();
const chokidar = require("chokidar");
const logger = require("../lib/cliLogger");

const NODE_MODULES_PATH = path.join(__dirname, "..", "..", "node_modules");
const MOCHA_PATH = path.join(NODE_MODULES_PATH, ".bin", "mocha");
const MOCHA_COVERAGE_PATH = path.join(NODE_MODULES_PATH, ".bin", "_mocha");
const MOCHA_TEST_PATH = `${CWD}/test/**/*.test.js`;
const MOCHA_HELPER_PATH = path.join(__dirname, "..", "lib", "testHelperMocha.js");
const BABEL_NODE_PATH = path.join(NODE_MODULES_PATH, ".bin", "babel-node");
const BABEL_ISTANBUL_PATH = path.join(NODE_MODULES_PATH, "babel-istanbul", "lib", "cli.js");
const INSPECTOR_PATH = path.join(NODE_MODULES_PATH, ".bin", "node-inspector");
const MOCHA_ENV = { ...process.env, ...{ NODE_PATH: CWD, NODE_ENV: "test" }};

function watchSources(callback) {
  // Debounce file watches
  let timeout;
  chokidar.watch([path.join(CWD, "src/**/*.js"), path.join(CWD, "test/**/*.js")], {
    ignored: /[\/\\]\./,
    persistent: true
  }).on("all", function() {
    clearTimeout(timeout);
    timeout = setTimeout(() => {
      callback();
    }, 250);
  });
}

function createMochaArgs(options, coverage) {
  const args = ["--require", MOCHA_HELPER_PATH];
  if (!coverage) {
    args.push("--reporter");
    args.push(options.reporter ? options.reporter : "dot");
  }
  args.push(MOCHA_TEST_PATH);
  if (options.debugTest) {
    args.push("--debug");
  }
  if (!options.single && !options.debugTest) {
    args.push("--watch");
  }
  return args;
}

/*
 * Run Mocha tests, handled differently with different options.
 *
 * @param {object} options            Command-line options in Commander format.
 * @param {string} options.reporter   Mocha reporter to use, ex. 'dot' or 'min'
 * @param {bool}   options.debugTest  Run test in debug mode. Assumes watch: false.
 * @param {bool}   options.single     Run once (watch: false).
 * @returns {object}                  Resulting process from spawn().
 *
 */
function useMocha(options) {
  const spawnOpts = {
    mocha: [
      MOCHA_PATH,
      createMochaArgs(options, false),
      {
        stdio: "inherit",
        env: MOCHA_ENV
      }
    ],
    coverage: [
      BABEL_NODE_PATH,
      [
        BABEL_ISTANBUL_PATH,
        "cover",
        "--include-all-sources",
        "--root",
        "src",
        "--report",
        "lcov",
        "--dir",
        "coverage/lcov",
        MOCHA_COVERAGE_PATH,
        ...createMochaArgs(options, true)
      ],
      {
        // Suppress error output since it includes the entire test run!
        stdio: "ignore",
        env: MOCHA_ENV
      }
    ],
    single: [
      BABEL_NODE_PATH,
      [
        BABEL_ISTANBUL_PATH,
        "cover",
        "--include-all-sources",
        "--root",
        "src",
        "--report",
        "cobertura",
        "--dir",
        "coverage/xml",
        MOCHA_COVERAGE_PATH,
        ...createMochaArgs(options, true)
      ],
      {
        stdio: "inherit",
        env: MOCHA_ENV
      }
    ]
  };

  if (options.debugTest) {
    debug();
  } else if (options.single) {
    spawn(...spawnOpts.single).on("exit", function(exitCode) {
      process.exit(exitCode);
    });
  } else {
    watch();
  }

  function debug() {
    // Start up the inspector and open it in a browser window.
    spawn(INSPECTOR_PATH, [], { stdio: "inherit" });
    spawn("open", ["http://127.0.0.1:8080/debug?port=5858"], { stdio: "inherit" });

    // Node segfaults when using debug with Mocha's built-in watch. Booooo!
    // Instead, we'll use Chokidar to watch - it's slower since it rebuilds each time, but it works, and isn't too
    // bad since debugging tests is expected to be a slower process than "save/see results".
    let running = false;
    watchSources(function() {
      if (running) {
        return;
      }
      running = true;
      const child = spawn(...spawnOpts.mocha);

      child.on("exit", function() {
        running = false;
      });
    });
  }

  function watch() {
    // If not debugging, start up mocha in watch mode.
    spawn(...spawnOpts.mocha);

    // Set up a watcher to create coverage reports in the background, only messaging on success/failure.
    // To ensure only the latest version is available, kill/restart the process on each change.
    let child;
    watchSources(function() {
      if (child) {
        child.kill();
      }
      child = spawn(...spawnOpts.coverage);
      child.on("exit", function(exitCode) {
        if (exitCode === 0) {
          logger.success("Coverage report generated.");
        } else if (exitCode === 1) {
          logger.error("Coverage report generated, but with test errors.");
        }
      });
    });
  }
}

function useKarma(options) {
  // override browser setting to use firefox instead of Chrome if specified
  if (options.firefox) {
    karmaConfig.browsers = ["Firefox"];
  }

  if (options.single) {
    karmaConfig.singleRun = options.single;
  }

  const server = new Server(karmaConfig);

  server.start();
  server.on("browsers_ready", function () {
    runner.run(karmaConfig, () => {});
  });
}

module.exports = function(options) {
  // override to run tests in Node without Karma/Webpack
  if (options.karma) {
    useKarma(options);
  } else {
    useMocha(options);
  }
};
<|endoftext|>


<commit_before>const FeedSelector = require('../structs/FeedSelector.js')
const Article = require('../structs/Article.js')
const MenuUtils = require('../structs/MenuUtils.js')
const FeedFetcher = require('../util/FeedFetcher.js')
const ArticleMessage = require('../structs/ArticleMessage.js')
const Translator = require('../structs/Translator.js')
const Profile = require('../structs/db/Profile.js')
const FailRecord = require('../structs/db/FailRecord.js')
const FeedData = require('../structs/FeedData.js')
const Supporter = require('../structs/db/Supporter.js')

module.exports = async (message, command) => {
  const simple = MenuUtils.extractArgsAfterCommand(message.content).includes('simple')
  const profile = await Profile.get(message.guild.id)
  const feedDatas = await FeedData.getManyBy('guild', message.guild.id)
  const feeds = feedDatas.map(data => data.feed)
  const guildLocale = profile ? profile.locale : undefined
  const translate = Translator.createLocaleTranslator(guildLocale)
  const feedSelector = new FeedSelector(message, null, { command: command }, feeds)
  const data = await new MenuUtils.MenuSeries(message, [feedSelector], { locale: guildLocale }).start()
  if (!data) {
    return
  }
  // This is the feed data
  const { feed } = data
  if (await FailRecord.hasFailed(feed.url)) {
    return message.channel.send(translate('commands.test.failed'))
  }
  const grabMsg = await message.channel.send(translate('commands.test.grabbingRandom'))
  const article = await FeedFetcher.fetchRandomArticle(feed.url)
  if (!article) {
    return message.channel.send(translate('commands.test.noArticles'))
  }
  article._feed = feedDatas.find(data => data.feed._id === feed._id).toJSON()
  if (Supporter.enabled && profile.webhook && !(await Supporter.hasValidGuild(message.guild.id))) {
    profile.webhook = undefined
    await profile.save()
  }

  if (!simple) {
    const parsedArticle = new Article(article, feed, profile || {})
    const testText = parsedArticle.createTestText()
    await message.channel.send(testText, {
      split: {
        prepend: '```md\n',
        append: '```'
      }
    })
  }

  const articleMessage = new ArticleMessage(message.client, article, true)
  await articleMessage.send()
  await grabMsg.delete()
}
<commit_msg>Move test to use discord.js-prompts<commit_after>const { PromptNode } = require('discord.js-prompts')
const commonPrompts = require('./prompts/common/index.js')
const runWithFeedGuild = require('./prompts/runner/runWithFeedsProfile.js')
const Article = require('../structs/Article.js')
const FeedFetcher = require('../util/FeedFetcher.js')
const ArticleMessage = require('../structs/ArticleMessage.js')
const Translator = require('../structs/Translator.js')
const Profile = require('../structs/db/Profile.js')
const FailRecord = require('../structs/db/FailRecord.js')
const FeedData = require('../structs/FeedData.js')
const Supporter = require('../structs/db/Supporter.js')

module.exports = async (message, command) => {
  const simple = message.content.endsWith('simple')
  const profile = await Profile.get(message.guild.id)
  const feedDatas = await FeedData.getManyBy('guild', message.guild.id)
  const translate = Translator.createProfileTranslator(profile)
  const selectFeedNode = new PromptNode(commonPrompts.selectFeed.prompt)
  const data = await runWithFeedGuild(selectFeedNode, message)
  const { selectedFeed: feed } = data
  if (!feed) {
    return
  }
  if (await FailRecord.hasFailed(feed.url)) {
    return message.channel.send(translate('commands.test.failed'))
  }
  const grabMsg = await message.channel.send(translate('commands.test.grabbingRandom'))
  const article = await FeedFetcher.fetchRandomArticle(feed.url)
  if (!article) {
    return message.channel.send(translate('commands.test.noArticles'))
  }
  article._feed = feedDatas.find(data => data.feed._id === feed._id).toJSON()
  if (Supporter.enabled && profile.webhook && !(await Supporter.hasValidGuild(message.guild.id))) {
    profile.webhook = undefined
    await profile.save()
  }

  if (!simple) {
    const parsedArticle = new Article(article, feed, profile || {})
    const testText = parsedArticle.createTestText()
    await message.channel.send(testText, {
      split: {
        prepend: '```md\n',
        append: '```'
      }
    })
  }

  const articleMessage = new ArticleMessage(message.client, article, true)
  await articleMessage.send()
  await grabMsg.delete()
}
<|endoftext|>


<commit_before>import React,{Component} from 'react';
import '../style/bootstrap.min.css';
 class Box extends Component{
    percent(){
    if(this.props.percent<0)
      return {this.props.percent}%;
      else
        return +{this.props.percent}%;
      }

    render(){
  return(

{this.props.name}

{this.percent()}

${this.props.usd}

  );
    }
}

export default Box;<commit_msg>fix column<commit_after>import React,{Component} from 'react';
import '../style/bootstrap.min.css';
 class Box extends Component{
    percent(){
    if(this.props.percent<0)
      return {this.props.percent}%;
      else
        return +{this.props.percent}%;
      }

    render(){
  return(

{this.props.name}

{this.percent()}

${this.props.usd}

  );
    }
}

export default Box;<|endoftext|>


<commit_before>/*
 *  Project: ContentSlider
 *  Description: A Simple ContentSlider with navigation
 *  Author: Malte Sohns
 *  License: MIT
 */

// the semi-colon before function invocation is a safety net against concatenated
// scripts and/or other plugins which may not be closed properly.
;
(function($, window, undefined) {

	// undefined is used here as the undefined global variable in ECMAScript 3 is
	// mutable (ie. it can be changed by someone else). undefined isn't really being
	// passed in so we can ensure the value of it is truly undefined. In ES5, undefined
	// can no longer be modified.

	// window and document are passed through as local variables rather than globals
	// as this (slightly) quickens the resolution process and can be more efficiently
	// minified (especially when both are regularly referenced in your plugin).

	// Create the defaults once
	var pluginName = 'contentSlider',
		document = window.document,
		defaults = {
			slideSpeed: 1000,
			animateType: 'swing',
			contentSize: 800
		};

	// The actual plugin constructor
	function Plugin(element, options) {
		this.element = element;

		// jQuery has an extend method which merges the contents of two or
		// more objects, storing the result in the first object. The first object
		// is generally empty as we don't want to alter the default options for
		// future instances of the plugin
		this.options = $.extend({}, defaults, options);

		this._defaults = defaults;
		this._name = pluginName;

		this.init();
	}

	Plugin.prototype.init = function() {
		// Place initialization logic here
		// You already have access to the DOM element and the options via the instance,
		// e.g., this.element and this.options
		var opt = this.options;

		var itemCount = $(".slider-navItem").length; //DO NOT CHANGE
		var contentWrapSize = opt.contentSize; //DO NOT CHANGE
		var contentContainer = opt.contentSize * itemCount; //DO NOT CHANGE
		var margLeft = 0; //DO NOT CHANGE
		var divHeight = $('.slider-content:eq(0)').height();

		// SET CSS SETTINGS
		$('.slider-content').css("width", opt.contentSize + 'px');
		$('#slider-contentContainer').css("width", contentContainer + 'px');
		$('#slider-contentWrap').css("width", contentWrapSize + 'px');
		$('#slider-contentWrap').css("height", divHeight + 'px');

		// This is the whole Slider function
		$('.slider-navItem').click(function() {
			var index = $(".slider-navItem").index($(this));
			var divSize = $('.slider-content:eq(' + index + ')').height();
			$("#slider-contentContainer").animate({
				marginLeft: margLeft - (opt.contentSize * index)
			}, {
				duration: opt.slideSpeed,
				queue: false
			});
			$("#slider-contentWrap").animate({
				height: divSize+'px'
			}, {
				duration: opt.slideSpeed,
				queue: false
			});
		});
	};

	// A really lightweight plugin wrapper around the constructor,
	// preventing against multiple instantiations
	$.fn[pluginName] = function(options) {
		return this.each(function() {
			if (!$.data(this, 'plugin_' + pluginName)) {
				$.data(this, 'plugin_' + pluginName, new Plugin(this, options));
			}
		});
	}

}(jQuery, window));<commit_msg>no message<commit_after>/*
 *  Project: ContentSlider
 *  Description: A Simple ContentSlider with navigation
 *  Author: Malte Sohns
 *  License: MIT
 */

;
(function($, window, undefined) {

	var pluginName = 'contentSlider',
		document = window.document,
		defaults = {
			slideSpeed: 1000,
			animateType: 'swing',
			contentSize: 800
		};

	function Plugin(element, options) {
		this.element = element;

		this.options = $.extend({}, defaults, options);

		this._defaults = defaults;
		this._name = pluginName;

		this.init();
	}

	Plugin.prototype.init = function() {

		var opt = this.options;

		var itemCount = $(".slider-navItem").length;
		var contentWrapSize = opt.contentSize;
		var contentContainer = opt.contentSize * itemCount;
		var margLeft = 0;
		var divHeight = $('.slider-content:eq(0)').height();

		$('.slider-content').css("width", opt.contentSize + 'px');
		$('#slider-contentContainer').css("width", contentContainer + 'px');
		$('#slider-contentWrap').css("width", contentWrapSize + 'px');
		$('#slider-contentWrap').css("height", divHeight + 'px');

		$('.slider-navItem').click(function() {
			var index = $(".slider-navItem").index($(this));
			var divSize = $('.slider-content:eq(' + index + ')').height();
			$("#slider-contentContainer").animate({
				marginLeft: margLeft - (opt.contentSize * index)
			}, {
				duration: opt.slideSpeed,
				queue: false
			});
			$("#slider-contentWrap").animate({
				height: divSize + 'px'
			}, {
				duration: opt.slideSpeed,
				queue: false
			});
		});
	};

	$.fn[pluginName] = function(options) {
		return this.each(function() {
			if (!$.data(this, 'plugin_' + pluginName)) {
				$.data(this, 'plugin_' + pluginName, new Plugin(this, options));
			}
		});
	}

}(jQuery, window));<|endoftext|>


<commit_before>const globals = {
  observer: null,
  target: null,
  ver: null,
  currentHref: null
};

const VER = {
  CLASSIC: 'ver classic',
  V2018: 'ver 2018'
};

// Sound service with audio pool
const Sound = {
  _audioPool: [],
  _inited: false,

  init() {
    if (this._inited) {
      return;
    }
    this._inited = true;
    this._growPool(5);
  },

  play() {
    const audio = this._getAvailableAudio();
    audio.play();
  },

  _growPool(count) {
    for (let i = 0; i < count; i++) {
      this._audioPool.push(this._createAudio());
    }
  },

  _createAudio() {
    const audio = new Audio(chrome.runtime.getURL('new_message.mp3'));
    audio.volume = 0.5;
    return audio;
  },

  _getAvailableAudio() {
    const poolSize = this._audioPool.length;
    for (let i = 0; i < poolSize; i++) {
      const audio = this._audioPool[i];

      if (audio.paused || audio.ended) {
        audio.currentTime = 0;
        return audio;
      }
    }

    // 來到這邊表示 pool 不太夠用，長大一倍
    // 上限 30
    if (poolSize < 30) {
      this._growPool(poolSize);
    }

    // 沒有可用的只好硬拿一個
    const audio = this._audioPool[0];
    audio.currentTime = 0;
    return audio;
  }
};

// requestInterval
// ref: https://github.com/nk-components/request-interval
const requestInterval = (function() {
  function interval(delay, fn) {
    var start = Date.now();
    var data = {};
    data.id = requestAnimationFrame(loop);

    return data;

    function loop() {
      data.id = requestAnimationFrame(loop);

      if (Date.now() - start >= delay) {
        fn();
        start = Date.now();
      }
    }
  }

  function clearInterval(data) {
    cancelAnimationFrame(data.id);
  }

  const self = interval;
  self.clear = clearInterval;
  return self;
})();

function _getChatRoomContent() {
  let content = null;
  let ver = null;

  // classic
  content = document.querySelector('.chat-room .tse-content');
  if (content) {
    ver = VER.CLASSIC;
    return { content, ver };
  }

  // 2018 react
  content = document.querySelector('.chat-list__lines .tw-full-height');
  if (content) {
    ver = VER.V2018;
    return { content, ver };
  }

  return { content, ver };
}

function getChatRoomContentAsync(timeout) {
  const delay = 100;
  const startedAt = now();
  return new Promise((resolve, reject) => {
    const interval = setInterval(() => {
      const { content, ver } = _getChatRoomContent();

      if (content) {
        clearInterval(interval);
        resolve({
          content,
          ver
        });
      }

      const timePassed = now() - startedAt;
      if (timePassed > timeout) {
        clearInterval(interval);
        reject();
      }
    }, delay);
  });
}

function slice(arraryLikeGuy) {
  return Array.prototype.slice.call(arraryLikeGuy);
}

function now() {
  return +new Date();
}

function main() {
  href = location.href;
  onPageRender();

  requestInterval(500, () => {
    if (location.href !== globals.currentHref) {
      globals.currentHref = location.href;
      onHrefChange();
    }
  });

  function onHrefChange() {
    deactivate();
    chrome.runtime.sendMessage('deactivateFromTab');

    globals.observer = null;
    globals.target = null;

    requestAnimationFrame(function() {
      onPageRender();
    });
  }

  function onPageRender() {
    getChatRoomContentAsync(10000).then(
      ({ content, ver }) => {
        Sound.init();

        globals.observer = new MutationObserver(onMutation);
        globals.target = content;
        globals.ver = ver;
      },
      () => {
        console.warn('[I Hear You] Chatroom DOM not found on this page');
      }
    );
  }

  function onMutation(mutations) {
    const m = mutations.filter(mutation => {
      if (!mutation.addedNodes || mutation.addedNodes.length === 0) {
        return false;
      }
      const newNode = mutation.addedNodes[0];

      // 必須是 element node
      if (newNode.nodeType !== Node.ELEMENT_NODE) {
        return false;
      }

      const classList = slice(newNode.classList);

      const ver = globals.ver;

      if (ver === VER.CLASSIC) {
        // 確定是聊天訊息的一種
        if (classList.indexOf('chat-line') < 0) {
          return false;
        }
        // 不是系統訊息
        if (classList.indexOf('admin') >= 0) {
          return false;
        }

        return true;
      }

      if (ver === VER.V2018) {
        // 是聊天訊息(不會是別的)
        // 新版用 BEM CSS 分得比較開
        if (classList.indexOf('chat-line__message') >= 0) {
          return true;
        }

        return false;
      }

      return false;
    });

    if (m.length > 0) {
      Sound.play();
    }
  }

  function activate() {
    if (!globals.observer) {
      return false;
    }
    globals.observer.observe(globals.target, {
      attributes: true,
      childList: true,
      characterData: true,
      subtree: true
    });
    return true;
  }

  function deactivate() {
    if (!globals.observer) {
      return false;
    }
    globals.observer.disconnect();
    return true;
  }

  function handleMessage(message, sender, sendResponse) {
    switch (message) {
      case 'activate':
        if (activate()) {
          sendResponse(true /* active */);
        } else {
          sendResponse(false /* active */);
        }
        break;
      case 'deactivate':
        if (deactivate()) {
          sendResponse(false /* active */);
        } else {
          sendResponse(true /* active */);
        }
        break;
    }
  }

  chrome.runtime.onMessage.addListener(handleMessage);
}

main();
<commit_msg>Add 2019 new design support<commit_after>const globals = {
  observer: null,
  target: null,
  ver: null,
  currentHref: null
};

const VER = {
  CLASSIC: 'ver classic',
  V2018: 'ver 2018',
  V2019: 'ver 2019'
};

// Sound service with audio pool
const Sound = {
  _audioPool: [],
  _inited: false,

  init() {
    if (this._inited) {
      return;
    }
    this._inited = true;
    this._growPool(5);
  },

  play() {
    const audio = this._getAvailableAudio();
    audio.play();
  },

  _growPool(count) {
    for (let i = 0; i < count; i++) {
      this._audioPool.push(this._createAudio());
    }
  },

  _createAudio() {
    const audio = new Audio(chrome.runtime.getURL('new_message.mp3'));
    audio.volume = 0.5;
    return audio;
  },

  _getAvailableAudio() {
    const poolSize = this._audioPool.length;
    for (let i = 0; i < poolSize; i++) {
      const audio = this._audioPool[i];

      if (audio.paused || audio.ended) {
        audio.currentTime = 0;
        return audio;
      }
    }

    // 來到這邊表示 pool 不太夠用，長大一倍
    // 上限 30
    if (poolSize < 30) {
      this._growPool(poolSize);
    }

    // 沒有可用的只好硬拿一個
    const audio = this._audioPool[0];
    audio.currentTime = 0;
    return audio;
  }
};

// requestInterval
// ref: https://github.com/nk-components/request-interval
const requestInterval = (function() {
  function interval(delay, fn) {
    var start = Date.now();
    var data = {};
    data.id = requestAnimationFrame(loop);

    return data;

    function loop() {
      data.id = requestAnimationFrame(loop);

      if (Date.now() - start >= delay) {
        fn();
        start = Date.now();
      }
    }
  }

  function clearInterval(data) {
    cancelAnimationFrame(data.id);
  }

  const self = interval;
  self.clear = clearInterval;
  return self;
})();

function _getChatRoomContent() {
  let content = null;
  let ver = null;

  // classic
  content = document.querySelector('.chat-room .tse-content');
  if (content) {
    ver = VER.CLASSIC;
    return { content, ver };
  }

  // 2018 react
  content = document.querySelector('.chat-list__lines .tw-full-height');
  if (content) {
    ver = VER.V2018;
    return { content, ver };
  }

  // 2019 new design
  content = document.querySelector('.chat-list__lines .chat-list__list-container');
  if (content) {
    ver = VER.V2019;
    return { content, ver };
  }

  return { content, ver };
}

function getChatRoomContentAsync(timeout) {
  const delay = 100;
  const startedAt = now();
  return new Promise((resolve, reject) => {
    const interval = setInterval(() => {
      const { content, ver } = _getChatRoomContent();

      if (content) {
        clearInterval(interval);
        resolve({
          content,
          ver
        });
      }

      const timePassed = now() - startedAt;
      if (timePassed > timeout) {
        clearInterval(interval);
        reject();
      }
    }, delay);
  });
}

function slice(arraryLikeGuy) {
  return Array.prototype.slice.call(arraryLikeGuy);
}

function now() {
  return +new Date();
}

function main() {
  href = location.href;
  onPageRender();

  requestInterval(500, () => {
    if (location.href !== globals.currentHref) {
      globals.currentHref = location.href;
      onHrefChange();
    }
  });

  function onHrefChange() {
    deactivate();
    chrome.runtime.sendMessage('deactivateFromTab');

    globals.observer = null;
    globals.target = null;

    requestAnimationFrame(function() {
      onPageRender();
    });
  }

  function onPageRender() {
    getChatRoomContentAsync(10000).then(
      ({ content, ver }) => {
        Sound.init();

        globals.observer = new MutationObserver(onMutation);
        globals.target = content;
        globals.ver = ver;
      },
      () => {
        console.warn('[I Hear You] Chatroom DOM not found on this page');
      }
    );
  }

  function onMutation(mutations) {
    const m = mutations.filter(mutation => {
      if (!mutation.addedNodes || mutation.addedNodes.length === 0) {
        return false;
      }
      const newNode = mutation.addedNodes[0];

      // 必須是 element node
      if (newNode.nodeType !== Node.ELEMENT_NODE) {
        return false;
      }

      const classList = slice(newNode.classList);

      const ver = globals.ver;

      if (ver === VER.CLASSIC) {
        // 確定是聊天訊息的一種
        if (classList.indexOf('chat-line') < 0) {
          return false;
        }
        // 不是系統訊息
        if (classList.indexOf('admin') >= 0) {
          return false;
        }

        return true;
      }

      if (ver === VER.V2018 || ver === VER.V2019) {
        // 是聊天訊息(不會是別的)
        // 新版用 BEM CSS 分得比較開
        if (classList.indexOf('chat-line__message') >= 0) {
          return true;
        }

        return false;
      }

      return false;
    });

    if (m.length > 0) {
      Sound.play();
    }
  }

  function activate() {
    if (!globals.observer) {
      return false;
    }
    globals.observer.observe(globals.target, {
      attributes: true,
      childList: true,
      characterData: true,
      subtree: true
    });
    return true;
  }

  function deactivate() {
    if (!globals.observer) {
      return false;
    }
    globals.observer.disconnect();
    return true;
  }

  function handleMessage(message, sender, sendResponse) {
    switch (message) {
      case 'activate':
        if (activate()) {
          sendResponse(true /* active */);
        } else {
          sendResponse(false /* active */);
        }
        break;
      case 'deactivate':
        if (deactivate()) {
          sendResponse(false /* active */);
        } else {
          sendResponse(true /* active */);
        }
        break;
    }
  }

  chrome.runtime.onMessage.addListener(handleMessage);
}

main();
<|endoftext|>


<commit_before>(function () {
    var moduleInjection = {};
    BI.module = BI.module || function (xtype, cls) {
        if (moduleInjection[xtype] != null) {
            _global.console && console.error("module： [" + xtype + "] 已经注册过了");
        }
        moduleInjection[xtype] = cls;
    };

    var constantInjection = {};
    BI.constant = BI.constant || function (xtype, cls) {
        if (constantInjection[xtype] != null) {
            _global.console && console.error("constant: [" + xtype + "]已经注册过了");
        }
        constantInjection[xtype] = cls;
    };

    var modelInjection = {};
    BI.model = BI.model || function (xtype, cls) {
        if (modelInjection[xtype] != null) {
            _global.console && console.error("model: [" + xtype + "] 已经注册过了");
        }
        modelInjection[xtype] = cls;
    };

    var storeInjection = {};
    BI.store = BI.store || function (xtype, cls) {
        if (storeInjection[xtype] != null) {
            _global.console && console.error("store: [" + xtype + "] 已经注册过了");
        }
        storeInjection[xtype] = cls;
    };

    var serviceInjection = {};
    BI.service = BI.service || function (xtype, cls) {
        if (serviceInjection[xtype] != null) {
            _global.console && console.error("service: [" + xtype + "] 已经注册过了");
        }
        serviceInjection[xtype] = cls;
    };

    var providerInjection = {};
    BI.provider = BI.provider || function (xtype, cls) {
        if (providerInjection[xtype] != null) {
            _global.console && console.error("provider: [" + xtype + "] 已经注册过了");
        }
        providerInjection[xtype] = cls;
    };

    var configFunctions = {};
    BI.config = BI.config || function (type, configFn, opt) {
        if (BI.initialized) {
            if (constantInjection[type]) {
                return (constantInjection[type] = configFn(constantInjection[type]));
            }
            if (providerInjection[type]) {
                if (!providers[type]) {
                    providers[type] = new providerInjection[type]();
                }
                // 如果config被重新配置的话，需要删除掉之前的实例
                if (providerInstance[type]) {
                    delete providerInstance[type];
                }
                return configFn(providers[type]);
            }
            return BI.Plugin.configWidget(type, configFn, opt);
        }
        if (!configFunctions[type]) {
            configFunctions[type] = [];
            BI.prepares.push(function () {
                var queue = configFunctions[type];
                for (var i = 0; i < queue.length; i++) {
                    if (constantInjection[type]) {
                        constantInjection[type] = queue[i](constantInjection[type]);
                        continue;
                    }
                    if (providerInjection[type]) {
                        if (!providers[type]) {
                            providers[type] = new providerInjection[type]();
                        }
                        if (providerInstance[type]) {
                            delete providerInstance[type];
                        }
                        queue[i](providers[type]);
                        continue;
                    }
                    BI.Plugin.configWidget(type, queue[i]);
                }
                configFunctions[type] = null;
            });
        }
        configFunctions[type].push(configFn);
    };

    BI.getReference = BI.getReference || function (type, fn) {
        return BI.Plugin.registerObject(type, fn);
    };

    var actions = {};
    var globalAction = [];
    BI.action = BI.action || function (type, actionFn) {
        if (BI.isFunction(type)) {
            globalAction.push(type);
            return function () {
                BI.remove(globalAction, function (idx) {
                    return globalAction.indexOf(actionFn) === idx;
                });
            };
        }
        if (!actions[type]) {
            actions[type] = [];
        }
        actions[type].push(actionFn);
        return function () {
            BI.remove(actions[type], function (idx) {
                return actions[type].indexOf(actionFn) === idx;
            });
            if (actions[type].length === 0) {
                delete actions[type];
            }
        };
    };

    var points = {};
    BI.point = BI.point || function (type, action, pointFn, after) {
        if (!points[type]) {
            points[type] = {};
        }
        if (!points[type][action]) {
            points[type][action] = {};
        }
        if (!points[type][action][after ? "after" : "before"]) {
            points[type][action][after ? "after" : "before"] = [];
        }
        points[type][action][after ? "after" : "before"].push(pointFn);
    };

    BI.Modules = BI.Modules || {
        getModule: function (type) {
            if (!moduleInjection[type]) {
                throw new Error("module: [" + type + "] 未定义");
            }
            return moduleInjection[type];
        },
        getAllModules: function () {
            return moduleInjection;
        }
    };

    BI.Constants = BI.Constants || {
        getConstant: function (type) {
            if (!constantInjection[type]) {
                throw new Error("constant: [" + type + "] 未定义");
            }
            return constantInjection[type];
        }
    };

    var callPoint = function (inst, types) {
        types = BI.isArray(types) ? types : [types];
        BI.each(types, function (idx, type) {
            if (points[type]) {
                for (var action in points[type]) {
                    var bfns = points[type][action].before;
                    if (bfns) {
                        BI.aspect.before(inst, action, function (bfns) {
                            return function () {
                                for (var i = 0, len = bfns.length; i < len; i++) {
                                    try {
                                        bfns[i].apply(inst, arguments);
                                    } catch (e) {
                                        _global.console && console.error(e);
                                    }
                                }
                            };
                        }(bfns));
                    }
                    var afns = points[type][action].after;
                    if (afns) {
                        BI.aspect.after(inst, action, function (afns) {
                            return function () {
                                for (var i = 0, len = afns.length; i < len; i++) {
                                    try {
                                        afns[i].apply(inst, arguments);
                                    } catch (e) {
                                        _global.console && console.error(e);
                                    }
                                }
                            };
                        }(afns));
                    }
                }
            }
        });
    };

    BI.Models = BI.Models || {
        getModel: function (type, config) {
            if (!modelInjection[type]) {
                throw new Error("model: [" + type + "] 未定义");
            }
            var inst = new modelInjection[type](config);
            inst._constructor && inst._constructor(config);
            inst.mixins && callPoint(inst, inst.mixins);
            callPoint(inst, type);
            return inst;
        }
    };

    var stores = {};

    BI.Stores = BI.Stores || {
        getStore: function (type, config) {
            if (!storeInjection[type]) {
                throw new Error("store: [" + type + "] 未定义");
            }
            if (stores[type]) {
                return stores[type];
            }
            var inst = stores[type] = new storeInjection[type](config);
            inst._constructor && inst._constructor(config, function () {
                delete stores[type];
            });
            callPoint(inst, type);
            return inst;
        }
    };

    var services = {};

    BI.Services = BI.Services || {
        getService: function (type, config) {
            if (!serviceInjection[type]) {
                throw new Error("service: [" + type + "] 未定义");
            }
            if (services[type]) {
                return services[type];
            }
            services[type] = new serviceInjection[type](config);
            callPoint(services[type], type);
            return services[type];
        }
    };

    var providers = {},
        providerInstance = {};

    BI.Providers = BI.Providers || {
        getProvider: function (type, config) {
            if (!providerInjection[type]) {
                throw new Error("provider: [" + type + "] 未定义");
            }
            if (!providers[type]) {
                providers[type] = new providerInjection[type]();
            }
            if (!providerInstance[type]) {
                providerInstance[type] = new (providers[type].$get())(config);
            }
            return providerInstance[type];
        }
    };

    BI.Actions = BI.Actions || {
        runAction: function (type, event, config) {
            BI.each(actions[type], function (i, act) {
                try {
                    act(event, config);
                } catch (e) {
                    _global.console && console.error(e);
                }
            });
        },
        runGlobalAction: function () {
            var args = [].slice.call(arguments);
            BI.each(globalAction, function (i, act) {
                try {
                    act.apply(null, args);
                } catch (e) {
                    _global.console && console.error(e);
                }
            });
        }
    };

    BI.getResource = BI.getResource || function (type, config) {
        if (constantInjection[type]) {
            return BI.Constants.getConstant(type);
        }
        if (modelInjection[type]) {
            return BI.Models.getModel(type, config);
        }
        if (storeInjection[type]) {
            return BI.Stores.getStore(type, config);
        }
        if (serviceInjection[type]) {
            return BI.Services.getService(type, config);
        }
        if (providerInjection[type]) {
            return BI.Providers.getProvider(type, config);
        }
        throw new Error("未知类型: [" + type + "] 未定义");
    };
})();
<commit_msg>无JIRA任务  fix: 改为console.error<commit_after>(function () {
    var moduleInjection = {};
    BI.module = BI.module || function (xtype, cls) {
        if (moduleInjection[xtype] != null) {
            _global.console && console.error("module： [" + xtype + "] 已经注册过了");
        }
        moduleInjection[xtype] = cls;
    };

    var constantInjection = {};
    BI.constant = BI.constant || function (xtype, cls) {
        if (constantInjection[xtype] != null) {
            _global.console && console.error("constant: [" + xtype + "]已经注册过了");
        }
        constantInjection[xtype] = cls;
    };

    var modelInjection = {};
    BI.model = BI.model || function (xtype, cls) {
        if (modelInjection[xtype] != null) {
            _global.console && console.error("model: [" + xtype + "] 已经注册过了");
        }
        modelInjection[xtype] = cls;
    };

    var storeInjection = {};
    BI.store = BI.store || function (xtype, cls) {
        if (storeInjection[xtype] != null) {
            _global.console && console.error("store: [" + xtype + "] 已经注册过了");
        }
        storeInjection[xtype] = cls;
    };

    var serviceInjection = {};
    BI.service = BI.service || function (xtype, cls) {
        if (serviceInjection[xtype] != null) {
            _global.console && console.error("service: [" + xtype + "] 已经注册过了");
        }
        serviceInjection[xtype] = cls;
    };

    var providerInjection = {};
    BI.provider = BI.provider || function (xtype, cls) {
        if (providerInjection[xtype] != null) {
            _global.console && console.error("provider: [" + xtype + "] 已经注册过了");
        }
        providerInjection[xtype] = cls;
    };

    var configFunctions = {};
    BI.config = BI.config || function (type, configFn, opt) {
        if (BI.initialized) {
            if (constantInjection[type]) {
                return (constantInjection[type] = configFn(constantInjection[type]));
            }
            if (providerInjection[type]) {
                if (!providers[type]) {
                    providers[type] = new providerInjection[type]();
                }
                // 如果config被重新配置的话，需要删除掉之前的实例
                if (providerInstance[type]) {
                    delete providerInstance[type];
                }
                return configFn(providers[type]);
            }
            return BI.Plugin.configWidget(type, configFn, opt);
        }
        if (!configFunctions[type]) {
            configFunctions[type] = [];
            BI.prepares.push(function () {
                var queue = configFunctions[type];
                for (var i = 0; i < queue.length; i++) {
                    if (constantInjection[type]) {
                        constantInjection[type] = queue[i](constantInjection[type]);
                        continue;
                    }
                    if (providerInjection[type]) {
                        if (!providers[type]) {
                            providers[type] = new providerInjection[type]();
                        }
                        if (providerInstance[type]) {
                            delete providerInstance[type];
                        }
                        queue[i](providers[type]);
                        continue;
                    }
                    BI.Plugin.configWidget(type, queue[i]);
                }
                configFunctions[type] = null;
            });
        }
        configFunctions[type].push(configFn);
    };

    BI.getReference = BI.getReference || function (type, fn) {
        return BI.Plugin.registerObject(type, fn);
    };

    var actions = {};
    var globalAction = [];
    BI.action = BI.action || function (type, actionFn) {
        if (BI.isFunction(type)) {
            globalAction.push(type);
            return function () {
                BI.remove(globalAction, function (idx) {
                    return globalAction.indexOf(actionFn) === idx;
                });
            };
        }
        if (!actions[type]) {
            actions[type] = [];
        }
        actions[type].push(actionFn);
        return function () {
            BI.remove(actions[type], function (idx) {
                return actions[type].indexOf(actionFn) === idx;
            });
            if (actions[type].length === 0) {
                delete actions[type];
            }
        };
    };

    var points = {};
    BI.point = BI.point || function (type, action, pointFn, after) {
        if (!points[type]) {
            points[type] = {};
        }
        if (!points[type][action]) {
            points[type][action] = {};
        }
        if (!points[type][action][after ? "after" : "before"]) {
            points[type][action][after ? "after" : "before"] = [];
        }
        points[type][action][after ? "after" : "before"].push(pointFn);
    };

    BI.Modules = BI.Modules || {
        getModule: function (type) {
            if (!moduleInjection[type]) {
                _global.console && console.error("module: [" + type + "] 未定义");
            }
            return moduleInjection[type];
        },
        getAllModules: function () {
            return moduleInjection;
        }
    };

    BI.Constants = BI.Constants || {
        getConstant: function (type) {
            if (!constantInjection[type]) {
                _global.console && console.error("constant: [" + type + "] 未定义");
            }
            return constantInjection[type];
        }
    };

    var callPoint = function (inst, types) {
        types = BI.isArray(types) ? types : [types];
        BI.each(types, function (idx, type) {
            if (points[type]) {
                for (var action in points[type]) {
                    var bfns = points[type][action].before;
                    if (bfns) {
                        BI.aspect.before(inst, action, function (bfns) {
                            return function () {
                                for (var i = 0, len = bfns.length; i < len; i++) {
                                    try {
                                        bfns[i].apply(inst, arguments);
                                    } catch (e) {
                                        _global.console && console.error(e);
                                    }
                                }
                            };
                        }(bfns));
                    }
                    var afns = points[type][action].after;
                    if (afns) {
                        BI.aspect.after(inst, action, function (afns) {
                            return function () {
                                for (var i = 0, len = afns.length; i < len; i++) {
                                    try {
                                        afns[i].apply(inst, arguments);
                                    } catch (e) {
                                        _global.console && console.error(e);
                                    }
                                }
                            };
                        }(afns));
                    }
                }
            }
        });
    };

    BI.Models = BI.Models || {
        getModel: function (type, config) {
            if (!modelInjection[type]) {
                _global.console && console.error("model: [" + type + "] 未定义");
            }
            var inst = new modelInjection[type](config);
            inst._constructor && inst._constructor(config);
            inst.mixins && callPoint(inst, inst.mixins);
            callPoint(inst, type);
            return inst;
        }
    };

    var stores = {};

    BI.Stores = BI.Stores || {
        getStore: function (type, config) {
            if (!storeInjection[type]) {
                _global.console && console.error("store: [" + type + "] 未定义");
            }
            if (stores[type]) {
                return stores[type];
            }
            var inst = stores[type] = new storeInjection[type](config);
            inst._constructor && inst._constructor(config, function () {
                delete stores[type];
            });
            callPoint(inst, type);
            return inst;
        }
    };

    var services = {};

    BI.Services = BI.Services || {
        getService: function (type, config) {
            if (!serviceInjection[type]) {
                _global.console && console.error("service: [" + type + "] 未定义");
            }
            if (services[type]) {
                return services[type];
            }
            services[type] = new serviceInjection[type](config);
            callPoint(services[type], type);
            return services[type];
        }
    };

    var providers = {},
        providerInstance = {};

    BI.Providers = BI.Providers || {
        getProvider: function (type, config) {
            if (!providerInjection[type]) {
                _global.console && console.error("provider: [" + type + "] 未定义");
            }
            if (!providers[type]) {
                providers[type] = new providerInjection[type]();
            }
            if (!providerInstance[type]) {
                providerInstance[type] = new (providers[type].$get())(config);
            }
            return providerInstance[type];
        }
    };

    BI.Actions = BI.Actions || {
        runAction: function (type, event, config) {
            BI.each(actions[type], function (i, act) {
                try {
                    act(event, config);
                } catch (e) {
                    _global.console && console.error(e);
                }
            });
        },
        runGlobalAction: function () {
            var args = [].slice.call(arguments);
            BI.each(globalAction, function (i, act) {
                try {
                    act.apply(null, args);
                } catch (e) {
                    _global.console && console.error(e);
                }
            });
        }
    };

    BI.getResource = BI.getResource || function (type, config) {
        if (constantInjection[type]) {
            return BI.Constants.getConstant(type);
        }
        if (modelInjection[type]) {
            return BI.Models.getModel(type, config);
        }
        if (storeInjection[type]) {
            return BI.Stores.getStore(type, config);
        }
        if (serviceInjection[type]) {
            return BI.Services.getService(type, config);
        }
        if (providerInjection[type]) {
            return BI.Providers.getProvider(type, config);
        }
        throw new Error("未知类型: [" + type + "] 未定义");
    };
})();
<|endoftext|>


<commit_before>(function () {
    var moduleInjection = {}, moduleInjectionMap = {
        components: {},
        constants: {},
        stores: {},
        services: {},
        models: {},
        providers: {}
    };
    BI.module = BI.module || function (xtype, cls) {
        if (moduleInjection[xtype] != null) {
            _global.console && console.error("module： [" + xtype + "] 已经注册过了");
        }
        if (BI.isFunction(cls)) {
            cls = cls();
        }
        for (var k in moduleInjectionMap) {
            if (cls[k]) {
                for (var key in cls[k]) {
                    if (!moduleInjectionMap[k]) {
                        continue;
                    }
                    if (!moduleInjectionMap[k][key]) {
                        moduleInjectionMap[k][key] = [];
                    }
                    moduleInjectionMap[k][key].push({
                        version: cls[k][key],
                        moduleId: xtype
                    });
                }
            }
        }
        moduleInjection[xtype] = cls;
    };

    var constantInjection = {};
    BI.constant = BI.constant || function (xtype, cls) {
        if (constantInjection[xtype] != null) {
            _global.console && console.error("constant: [" + xtype + "]已经注册过了");
        }
        constantInjection[xtype] = cls;
    };

    var modelInjection = {};
    BI.model = BI.model || function (xtype, cls) {
        if (modelInjection[xtype] != null) {
            _global.console && console.error("model: [" + xtype + "] 已经注册过了");
        }
        modelInjection[xtype] = cls;
    };

    var storeInjection = {};
    BI.store = BI.store || function (xtype, cls) {
        if (storeInjection[xtype] != null) {
            _global.console && console.error("store: [" + xtype + "] 已经注册过了");
        }
        storeInjection[xtype] = cls;
    };

    var serviceInjection = {};
    BI.service = BI.service || function (xtype, cls) {
        if (serviceInjection[xtype] != null) {
            _global.console && console.error("service: [" + xtype + "] 已经注册过了");
        }
        serviceInjection[xtype] = cls;
    };

    var providerInjection = {};
    BI.provider = BI.provider || function (xtype, cls) {
        if (providerInjection[xtype] != null) {
            _global.console && console.error("provider: [" + xtype + "] 已经注册过了");
        }
        providerInjection[xtype] = cls;
    };

    var configFunctions = {};
    BI.config = BI.config || function (type, configFn, opt) {
        opt = opt || {};
        // 初始化过或者系统配置需要立刻执行
        if (BI.initialized || "bi.provider.system" === type) {
            if (constantInjection[type]) {
                return (constantInjection[type] = configFn(constantInjection[type]));
            }
            if (providerInjection[type]) {
                if (!providers[type]) {
                    providers[type] = new providerInjection[type]();
                }
                // 如果config被重新配置的话，需要删除掉之前的实例
                if (providerInstance[type]) {
                    delete providerInstance[type];
                }
                return configFn(providers[type]);
            }
            return BI.Plugin.configWidget(type, configFn, opt);
        }
        if (!configFunctions[type]) {
            configFunctions[type] = [];
            BI.prepares.push(function () {
                var queue = configFunctions[type];
                var dependencies = BI.Providers.getProvider("bi.provider.system").getDependencies();
                var modules = moduleInjectionMap.components[type]
                    || moduleInjectionMap.constants[type]
                    || moduleInjectionMap.services[type]
                    || moduleInjectionMap.stores[type]
                    || moduleInjectionMap.models[type]
                    || moduleInjectionMap.providers[type];
                for (var i = 0; i < queue.length; i++) {
                    var conf = queue[i];
                    var version = conf.opt.version;
                    var fn = conf.fn;
                    if (modules && version) {
                        var findVersion = false;
                        for (var j = 0; j < modules.length; j++) {
                            var module = modules[i];
                            if (module && dependencies[module.moduleId] && module.version === version) {
                                var minVersion = dependencies[module.moduleId].minVersion,
                                    maxVersion = dependencies[module.moduleId].maxVersion;
                                if (minVersion && (moduleInjection[module.moduleId].version || version) < minVersion) {
                                    findVersion = true;
                                    break;
                                }
                                if (maxVersion && (moduleInjection[module.moduleId].version || version) > maxVersion) {
                                    findVersion = true;
                                    break;
                                }
                            }
                        }
                        if (findVersion === true) {
                            _global.console && console.error("moduleId: [" + module.moduleId + "] 接口: [" + type + "] 接口版本: [" + version + "] 已过期，版本要求为：", dependencies[module.moduleId], "=>",  moduleInjection[module.moduleId]);
                            continue;
                        }
                    }
                    if (constantInjection[type]) {
                        constantInjection[type] = fn(constantInjection[type]);
                        continue;
                    }
                    if (providerInjection[type]) {
                        if (!providers[type]) {
                            providers[type] = new providerInjection[type]();
                        }
                        if (providerInstance[type]) {
                            delete providerInstance[type];
                        }
                        fn(providers[type]);
                        continue;
                    }
                    BI.Plugin.configWidget(type, fn);
                }
                configFunctions[type] = null;
            });
        }
        configFunctions[type].push({
            fn: configFn,
            opt: opt
        });
    };

    BI.getReference = BI.getReference || function (type, fn) {
        return BI.Plugin.registerObject(type, fn);
    };

    var actions = {};
    var globalAction = [];
    BI.action = BI.action || function (type, actionFn) {
        if (BI.isFunction(type)) {
            globalAction.push(type);
            return function () {
                BI.remove(globalAction, function (idx) {
                    return globalAction.indexOf(actionFn) === idx;
                });
            };
        }
        if (!actions[type]) {
            actions[type] = [];
        }
        actions[type].push(actionFn);
        return function () {
            BI.remove(actions[type], function (idx) {
                return actions[type].indexOf(actionFn) === idx;
            });
            if (actions[type].length === 0) {
                delete actions[type];
            }
        };
    };

    var points = {};
    BI.point = BI.point || function (type, action, pointFn, after) {
        if (!points[type]) {
            points[type] = {};
        }
        if (!points[type][action]) {
            points[type][action] = {};
        }
        if (!points[type][action][after ? "after" : "before"]) {
            points[type][action][after ? "after" : "before"] = [];
        }
        points[type][action][after ? "after" : "before"].push(pointFn);
    };

    BI.Modules = BI.Modules || {
        getModule: function (type) {
            if (!moduleInjection[type]) {
                _global.console && console.error("module: [" + type + "] 未定义");
            }
            return moduleInjection[type];
        },
        getAllModules: function () {
            return moduleInjection;
        }
    };

    BI.Constants = BI.Constants || {
        getConstant: function (type) {
            if (!constantInjection[type]) {
                _global.console && console.error("constant: [" + type + "] 未定义");
            }
            return constantInjection[type];
        }
    };

    var callPoint = function (inst, types) {
        types = BI.isArray(types) ? types : [types];
        BI.each(types, function (idx, type) {
            if (points[type]) {
                for (var action in points[type]) {
                    var bfns = points[type][action].before;
                    if (bfns) {
                        BI.aspect.before(inst, action, function (bfns) {
                            return function () {
                                for (var i = 0, len = bfns.length; i < len; i++) {
                                    try {
                                        bfns[i].apply(inst, arguments);
                                    } catch (e) {
                                        _global.console && console.error(e);
                                    }
                                }
                            };
                        }(bfns));
                    }
                    var afns = points[type][action].after;
                    if (afns) {
                        BI.aspect.after(inst, action, function (afns) {
                            return function () {
                                for (var i = 0, len = afns.length; i < len; i++) {
                                    try {
                                        afns[i].apply(inst, arguments);
                                    } catch (e) {
                                        _global.console && console.error(e);
                                    }
                                }
                            };
                        }(afns));
                    }
                }
            }
        });
    };

    BI.Models = BI.Models || {
        getModel: function (type, config) {
            if (!modelInjection[type]) {
                _global.console && console.error("model: [" + type + "] 未定义");
            }
            var inst = new modelInjection[type](config);
            inst._constructor && inst._constructor(config);
            inst.mixins && callPoint(inst, inst.mixins);
            callPoint(inst, type);
            return inst;
        }
    };

    var stores = {};

    BI.Stores = BI.Stores || {
        getStore: function (type, config) {
            if (!storeInjection[type]) {
                _global.console && console.error("store: [" + type + "] 未定义");
            }
            if (stores[type]) {
                return stores[type];
            }
            var inst = stores[type] = new storeInjection[type](config);
            inst._constructor && inst._constructor(config, function () {
                delete stores[type];
            });
            callPoint(inst, type);
            return inst;
        }
    };

    var services = {};

    BI.Services = BI.Services || {
        getService: function (type, config) {
            if (!serviceInjection[type]) {
                _global.console && console.error("service: [" + type + "] 未定义");
            }
            if (services[type]) {
                return services[type];
            }
            services[type] = new serviceInjection[type](config);
            callPoint(services[type], type);
            return services[type];
        }
    };

    var providers = {},
        providerInstance = {};

    BI.Providers = BI.Providers || {
        getProvider: function (type, config) {
            if (!providerInjection[type]) {
                _global.console && console.error("provider: [" + type + "] 未定义");
            }
            if (!providers[type]) {
                providers[type] = new providerInjection[type]();
            }
            if (!providerInstance[type]) {
                providerInstance[type] = new (providers[type].$get())(config);
            }
            return providerInstance[type];
        }
    };

    BI.Actions = BI.Actions || {
        runAction: function (type, event, config) {
            BI.each(actions[type], function (i, act) {
                try {
                    act(event, config);
                } catch (e) {
                    _global.console && console.error(e);
                }
            });
        },
        runGlobalAction: function () {
            var args = [].slice.call(arguments);
            BI.each(globalAction, function (i, act) {
                try {
                    act.apply(null, args);
                } catch (e) {
                    _global.console && console.error(e);
                }
            });
        }
    };

    BI.getResource = BI.getResource || function (type, config) {
        if (constantInjection[type]) {
            return BI.Constants.getConstant(type);
        }
        if (modelInjection[type]) {
            return BI.Models.getModel(type, config);
        }
        if (storeInjection[type]) {
            return BI.Stores.getStore(type, config);
        }
        if (serviceInjection[type]) {
            return BI.Services.getService(type, config);
        }
        if (providerInjection[type]) {
            return BI.Providers.getProvider(type, config);
        }
        throw new Error("未知类型: [" + type + "] 未定义");
    };
})();
<commit_msg>无JIRA任务 fix: 兼容constant定义为0的场景<commit_after>(function () {
    var moduleInjection = {}, moduleInjectionMap = {
        components: {},
        constants: {},
        stores: {},
        services: {},
        models: {},
        providers: {}
    };
    BI.module = BI.module || function (xtype, cls) {
        if (moduleInjection[xtype] != null) {
            _global.console && console.error("module： [" + xtype + "] 已经注册过了");
        }
        if (BI.isFunction(cls)) {
            cls = cls();
        }
        for (var k in moduleInjectionMap) {
            if (cls[k]) {
                for (var key in cls[k]) {
                    if (!moduleInjectionMap[k]) {
                        continue;
                    }
                    if (!moduleInjectionMap[k][key]) {
                        moduleInjectionMap[k][key] = [];
                    }
                    moduleInjectionMap[k][key].push({
                        version: cls[k][key],
                        moduleId: xtype
                    });
                }
            }
        }
        moduleInjection[xtype] = cls;
    };

    var constantInjection = {};
    BI.constant = BI.constant || function (xtype, cls) {
        if (constantInjection[xtype] != null) {
            _global.console && console.error("constant: [" + xtype + "]已经注册过了");
        }
        constantInjection[xtype] = cls;
    };

    var modelInjection = {};
    BI.model = BI.model || function (xtype, cls) {
        if (modelInjection[xtype] != null) {
            _global.console && console.error("model: [" + xtype + "] 已经注册过了");
        }
        modelInjection[xtype] = cls;
    };

    var storeInjection = {};
    BI.store = BI.store || function (xtype, cls) {
        if (storeInjection[xtype] != null) {
            _global.console && console.error("store: [" + xtype + "] 已经注册过了");
        }
        storeInjection[xtype] = cls;
    };

    var serviceInjection = {};
    BI.service = BI.service || function (xtype, cls) {
        if (serviceInjection[xtype] != null) {
            _global.console && console.error("service: [" + xtype + "] 已经注册过了");
        }
        serviceInjection[xtype] = cls;
    };

    var providerInjection = {};
    BI.provider = BI.provider || function (xtype, cls) {
        if (providerInjection[xtype] != null) {
            _global.console && console.error("provider: [" + xtype + "] 已经注册过了");
        }
        providerInjection[xtype] = cls;
    };

    var configFunctions = {};
    BI.config = BI.config || function (type, configFn, opt) {
        opt = opt || {};
        // 初始化过或者系统配置需要立刻执行
        if (BI.initialized || "bi.provider.system" === type) {
            if (constantInjection[type]) {
                return (constantInjection[type] = configFn(constantInjection[type]));
            }
            if (providerInjection[type]) {
                if (!providers[type]) {
                    providers[type] = new providerInjection[type]();
                }
                // 如果config被重新配置的话，需要删除掉之前的实例
                if (providerInstance[type]) {
                    delete providerInstance[type];
                }
                return configFn(providers[type]);
            }
            return BI.Plugin.configWidget(type, configFn, opt);
        }
        if (!configFunctions[type]) {
            configFunctions[type] = [];
            BI.prepares.push(function () {
                var queue = configFunctions[type];
                var dependencies = BI.Providers.getProvider("bi.provider.system").getDependencies();
                var modules = moduleInjectionMap.components[type]
                    || moduleInjectionMap.constants[type]
                    || moduleInjectionMap.services[type]
                    || moduleInjectionMap.stores[type]
                    || moduleInjectionMap.models[type]
                    || moduleInjectionMap.providers[type];
                for (var i = 0; i < queue.length; i++) {
                    var conf = queue[i];
                    var version = conf.opt.version;
                    var fn = conf.fn;
                    if (modules && version) {
                        var findVersion = false;
                        for (var j = 0; j < modules.length; j++) {
                            var module = modules[i];
                            if (module && dependencies[module.moduleId] && module.version === version) {
                                var minVersion = dependencies[module.moduleId].minVersion,
                                    maxVersion = dependencies[module.moduleId].maxVersion;
                                if (minVersion && (moduleInjection[module.moduleId].version || version) < minVersion) {
                                    findVersion = true;
                                    break;
                                }
                                if (maxVersion && (moduleInjection[module.moduleId].version || version) > maxVersion) {
                                    findVersion = true;
                                    break;
                                }
                            }
                        }
                        if (findVersion === true) {
                            _global.console && console.error("moduleId: [" + module.moduleId + "] 接口: [" + type + "] 接口版本: [" + version + "] 已过期，版本要求为：", dependencies[module.moduleId], "=>", moduleInjection[module.moduleId]);
                            continue;
                        }
                    }
                    if (constantInjection[type]) {
                        constantInjection[type] = fn(constantInjection[type]);
                        continue;
                    }
                    if (providerInjection[type]) {
                        if (!providers[type]) {
                            providers[type] = new providerInjection[type]();
                        }
                        if (providerInstance[type]) {
                            delete providerInstance[type];
                        }
                        fn(providers[type]);
                        continue;
                    }
                    BI.Plugin.configWidget(type, fn);
                }
                configFunctions[type] = null;
            });
        }
        configFunctions[type].push({
            fn: configFn,
            opt: opt
        });
    };

    BI.getReference = BI.getReference || function (type, fn) {
        return BI.Plugin.registerObject(type, fn);
    };

    var actions = {};
    var globalAction = [];
    BI.action = BI.action || function (type, actionFn) {
        if (BI.isFunction(type)) {
            globalAction.push(type);
            return function () {
                BI.remove(globalAction, function (idx) {
                    return globalAction.indexOf(actionFn) === idx;
                });
            };
        }
        if (!actions[type]) {
            actions[type] = [];
        }
        actions[type].push(actionFn);
        return function () {
            BI.remove(actions[type], function (idx) {
                return actions[type].indexOf(actionFn) === idx;
            });
            if (actions[type].length === 0) {
                delete actions[type];
            }
        };
    };

    var points = {};
    BI.point = BI.point || function (type, action, pointFn, after) {
        if (!points[type]) {
            points[type] = {};
        }
        if (!points[type][action]) {
            points[type][action] = {};
        }
        if (!points[type][action][after ? "after" : "before"]) {
            points[type][action][after ? "after" : "before"] = [];
        }
        points[type][action][after ? "after" : "before"].push(pointFn);
    };

    BI.Modules = BI.Modules || {
        getModule: function (type) {
            if (!moduleInjection[type]) {
                _global.console && console.error("module: [" + type + "] 未定义");
            }
            return moduleInjection[type];
        },
        getAllModules: function () {
            return moduleInjection;
        }
    };

    BI.Constants = BI.Constants || {
        getConstant: function (type) {
            if (BI.isNull(constantInjection[type])) {
                _global.console && console.error("constant: [" + type + "] 未定义");
            }
            return constantInjection[type];
        }
    };

    var callPoint = function (inst, types) {
        types = BI.isArray(types) ? types : [types];
        BI.each(types, function (idx, type) {
            if (points[type]) {
                for (var action in points[type]) {
                    var bfns = points[type][action].before;
                    if (bfns) {
                        BI.aspect.before(inst, action, function (bfns) {
                            return function () {
                                for (var i = 0, len = bfns.length; i < len; i++) {
                                    try {
                                        bfns[i].apply(inst, arguments);
                                    } catch (e) {
                                        _global.console && console.error(e);
                                    }
                                }
                            };
                        }(bfns));
                    }
                    var afns = points[type][action].after;
                    if (afns) {
                        BI.aspect.after(inst, action, function (afns) {
                            return function () {
                                for (var i = 0, len = afns.length; i < len; i++) {
                                    try {
                                        afns[i].apply(inst, arguments);
                                    } catch (e) {
                                        _global.console && console.error(e);
                                    }
                                }
                            };
                        }(afns));
                    }
                }
            }
        });
    };

    BI.Models = BI.Models || {
        getModel: function (type, config) {
            if (!modelInjection[type]) {
                _global.console && console.error("model: [" + type + "] 未定义");
            }
            var inst = new modelInjection[type](config);
            inst._constructor && inst._constructor(config);
            inst.mixins && callPoint(inst, inst.mixins);
            callPoint(inst, type);
            return inst;
        }
    };

    var stores = {};

    BI.Stores = BI.Stores || {
        getStore: function (type, config) {
            if (!storeInjection[type]) {
                _global.console && console.error("store: [" + type + "] 未定义");
            }
            if (stores[type]) {
                return stores[type];
            }
            var inst = stores[type] = new storeInjection[type](config);
            inst._constructor && inst._constructor(config, function () {
                delete stores[type];
            });
            callPoint(inst, type);
            return inst;
        }
    };

    var services = {};

    BI.Services = BI.Services || {
        getService: function (type, config) {
            if (!serviceInjection[type]) {
                _global.console && console.error("service: [" + type + "] 未定义");
            }
            if (services[type]) {
                return services[type];
            }
            services[type] = new serviceInjection[type](config);
            callPoint(services[type], type);
            return services[type];
        }
    };

    var providers = {},
        providerInstance = {};

    BI.Providers = BI.Providers || {
        getProvider: function (type, config) {
            if (!providerInjection[type]) {
                _global.console && console.error("provider: [" + type + "] 未定义");
            }
            if (!providers[type]) {
                providers[type] = new providerInjection[type]();
            }
            if (!providerInstance[type]) {
                providerInstance[type] = new (providers[type].$get())(config);
            }
            return providerInstance[type];
        }
    };

    BI.Actions = BI.Actions || {
        runAction: function (type, event, config) {
            BI.each(actions[type], function (i, act) {
                try {
                    act(event, config);
                } catch (e) {
                    _global.console && console.error(e);
                }
            });
        },
        runGlobalAction: function () {
            var args = [].slice.call(arguments);
            BI.each(globalAction, function (i, act) {
                try {
                    act.apply(null, args);
                } catch (e) {
                    _global.console && console.error(e);
                }
            });
        }
    };

    BI.getResource = BI.getResource || function (type, config) {
        if (BI.isNotNull(constantInjection[type])) {
            return BI.Constants.getConstant(type);
        }
        if (modelInjection[type]) {
            return BI.Models.getModel(type, config);
        }
        if (storeInjection[type]) {
            return BI.Stores.getStore(type, config);
        }
        if (serviceInjection[type]) {
            return BI.Services.getService(type, config);
        }
        if (providerInjection[type]) {
            return BI.Providers.getProvider(type, config);
        }
        throw new Error("未知类型: [" + type + "] 未定义");
    };
})();
<|endoftext|>


<commit_before>'use strict';

/*
 * Entry Observer object Constructor
 * @param {object} obj
 */
Entry.Observer = function(parent, object, funcName, attrs) {
    this.parent = parent;
    this.object = object;
    this.funcName = funcName;
    this.attrs = attrs;
    parent.push(this);
};

(function(p) {
    p.destroy = function() {
        var parent = this.parent;
        var index = parent.indexOf(this);
        if (index > -1) parent.splice(index, 1);
        return this;
    };
})(Entry.Observer.prototype);
<commit_msg>edit observer.js transfer class<commit_after>'use strict';

/*
 * Entry Observer object Constructor
 * @param {object} obj
 */

Entry.Observer = class Observer {
    constructor(parent, object, funcName, attrs) {
        this.parent = parent;
        this.object = object;
        this.funcName = funcName;
        this.attrs = attrs;
        parent.push(this);
    }

    destroy = function() {
        const parent = this.parent;
        const index = parent.indexOf(this);
        if (index > -1) {
            parent.splice(index, 1);
        }
        return this;
    };
};
<|endoftext|>