Publish a wxh-tools for your own npm package

Work is often repeated to write some methods, organized and hosted to In GitHub Warehouse ,
Build an npm package, each time used, download and package into a file on demand, easy to use;
<!--more-->

Project address

NPM address: https://www.npmjs.com/package/wxh-tools;

GITHUB: https://github.com/Wxh16144/wxh-tools;

Tool screenshots:

Project catalogue

  • bin

    • Www <span style= "font-size:.8em; color: green">//execute package commands
  • config

    • Methods_list.json <span style= "font-size:.8em; color: green">//all/src/tools/list of methods below, created by create_methods_list.js
    • webpack.config.js <span style= "font-size:.8em; color: green">//web pack configuration used for packaging
  • Dist <span style= "font-size:.8em; color: green">//packaged directory
  • Reoisutiry < span style= "font-size:.8em; color: green">// temporary directory for storing resources downloaded from git to local
  • src

    • Tools <span style= "font-size:.8em; color: green">// Store commonly used methods (all)
    • utils

      • Create_file_by_user_select.js <span style= "font-size:.8em; color: green">// / Create folders according to the method selected by the user
      • Get_json_file.js <span style= "font-size:.8em; color: green">// Read and serialize the contents of JSON file
      • Read_dir_file.js < span style= "font-size:.8em; color: green">// read all files in a directory
      • Webpack_build.js <span style= "font-size:.8em; color: green">// webpack configuration
    • Get.js < span style = "font-size:.8em; color: green">// download files from git
    • Index.js < span style= "font-size:.8em; color: green">// Get user selection config
    • Main.js < span style= "font-size:.8em; color: green">// entry file
  • .babelrc
  • Create_methods_list.js <span style= "font-size:.8em; color: green">//read src/tools/all methods and generate files

Installation dependency

  npm install @babel/cli@7.5.5  @babel/core@7.5.5  @babel/preset-env@7.5.5  babel-loader@8.0.0-beta.0  core-js@3.1.4  download@7.1.0  inquirer@6.5.0  ora@3.4.0  rimraf@2.6.3  shelljs@0.8.3  webpack@4.37.0  webpack-cli@3.3.6 --save

The enumerated npm statements are too long. In order to be lazy, I also use src/utils/get_json_file.js method.

Demo:

  const method = require('./src/utils/get_json_file');
  const json_file = method('./package.json');
  const dep = json_file.dependencies;
  const res = Object.keys(dep).reduce((str, key) => {
    return `${str}  ${key}@${(dep[key]).slice(1)}`
  }, '')
  console.log(res);
  // @babel/cli@7.5.5  @babel/core@7.5.5  @babel/preset-env@7.5.5  babel-loader@8.0.0-beta.0  core-js@3.1.4  download@7.1.0  inquirer@6.5.0  ora@3.4.0  rimraf@2.6.3  shelljs@0.8.3  webpack@4.37.0  webpack-cli@3.3.6

Tool Packaging

get_json_file.js

Read the json file and serialize it

  const fs = require('fs');
  /**
  *Read the *. JSON file and serialize it back
  *
  * @param {*} filepath File Address
  * @returns Document content
  */
  module.exports = (filepath) => {
    if (!filepath) return '';
    const _Json = fs.readFileSync(filepath);
    return JSON.parse(_Json);
  };

read_dir_file.js

Read all files in a directory (excluding folders, no recursion)

  const path = require('path');
  const path_join = path.join;
  const fs = require('fs');

  /**
  *Get all files in the directory (excluding folders)
  *
  * @param {*} [dir=path_join(__dirname)] Catalog
  * @param {*} [reg=/./] Regular expression of death
  * @returns File array
  */
  module.exports = (dir = path_join(__dirname), reg = /./) => {
    // Read all files
    let files = fs.readdirSync(dir);
    return files.reduce((arr, item) => {
      // Get the file path
      let fPath = path_join(dir, item);
      // read
      let stat = fs.statSync(fPath);
      // Determine whether it is a document or not
      let isFile = stat.isFile();
      // Filtering Regular Expression Conditions
      return isFile && reg.test(item) ? [...arr, item] : arr
    }, []);
  };

get.js

Download files from remote github repositories
download file packages; download npm address;

const path = require('path');
const path_join = path.join;
const fs = require('fs');
const download = require('download');

/**
 *Download files from remote github repositories
 *
 * @param {array} files file name
 * @param {string} [savePath=path_join(__dirname, '../repository')] File Download and Save Address
 * @returns Promise
 */
module.exports = (files, savePath = path_join(__dirname, '../repository')) => {
  const URL = 'https://raw.githubusercontent.com/Wxh16144/wxh-tools/master/';
  return Promise.all((Array.isArray(files) ? files : [])
    .map(file_name => download(URL + file_name, savePath)));
};

The tool is ready to complete and start building CONFIG (index.js)

Use the inquirer console interaction package; inquirer npm address;
Load animation packages using ora; ora npm address;

Introduce required modules

// Path Processing
const path = require('path');
const path_join = path.join;

// Communication through console
const inquirer = require('inquirer');
const prompt = inquirer.createPromptModule();
// Load animation
const ora = require('ora');

// Get the download file
const download_methods_list = require('./get');

Console interaction, a Promise array;

// Ask for additional methods
const Ask_the_task = [
  // Ask users what methods they need to use
  async () => {
    // Add animation
    const spinner = ora('Getting a list of all methods...').start();
    // Download a list of all methods
    const res = await download_methods_list(['config/methods_list.json']);
    // Reading method list
    const methods_list = require('./utils/get_json_file')(path_join(__dirname, '../repository/methods_list.json'));
    // Stop animation
    spinner.stop();
    const ALL_TOOLS_SERVER = (methods_list.methods_list || []).map(filename => {
      return filename.replace(/\.js$/, '');
    });
    // Create problems
    return prompt({
      type: 'checkbox',
      name: 'tools_key',
      message: 'Please choose the method you need.',
      default: [],
      choices: ALL_TOOLS_SERVER
    })
  },
  // Ask the user to save the name
  () => prompt({
    type: 'input',
    name: 'save_file_name',
    message: 'Save File Name',
    default: 'utils.js',
  }),
  // Ask users if they need to pack
  () => prompt({
    type: 'confirm',
    name: 'is_build',
    message: 'Need to use webpack Pack',
    default: true
  }),
];

Ask questions from top to bottom
CONFIG selected by users is merged to derive the execution method.

/**
 *Cyclic Questioning
 *
 * @returns User Configuration
 */
const task = async () => {
  const config = {};
  for (const fn of Ask_the_task) {
    const P = fn();
    const res = await P;
    Object.assign(config, res)
  }
  return config;
};

// Derived Questioning Method
module.exports = task;

Download the corresponding method (main.js) according to the user's choice

Use rimraf to delete file packages; rimraf npm address;

Loading module

const path = require('path');
const path_join = path.join;
const fs = require('fs');

// Delete files
const rimraf = require('rimraf');

// Get the download file
const download_methods_list = require('./get');

// Load animation
const ora = require('ora');

// Web pack packaging
const webpack_build_function = require('./utils/webpack_build');

// Interaction issues
const task = require('./index');

Ask the user, download the method locally, merge the method files, and pack with webpack

// All questions
const task = require('./index');
(async function () {
  const CONFIG = await task();
  // Getting User Configuration
  const { tools_key = [], is_build = true } = CONFIG;
  // Temporary catalogue
  const DIRECTORY = path_join(__dirname, '../temporary/');
  rimraf.sync(DIRECTORY);
  // Add download animation
  const download_spinner = ora('Downloading the selected method data...').start();
  // Collection according to the selected method
  // Download a list of all methods
  const load_select_methods = await download_methods_list(
    tools_key.map(key => `src/tools/${key}.js`),
    path_join(__dirname, '../temporary')
  );
  // Download completed
  download_spinner.succeed('The required method is downloaded');
  // Add Create File Animation
  const create_file_spinner = ora('Create and generate files...').start();
  const create_file_by_user_select = require('./utils/create_file_by_user_select');
  const create_file = await create_file_by_user_select(CONFIG);
  create_file_spinner.succeed('Create Completion');

  // Add packaged animation
  const build_spinner = ora('Processing files...').start();
  const build_res = await webpack_build_function(CONFIG);
  build_spinner.succeed(`Handling Success,address:${build_res}`);
}());

Create a merge file (create_file_by_user_select.js)

The method of downloading github to local temporary directory;
Packed files will have a global set of methods called WT in Windows

const path = require('path');
const path_join = path.join;
const fs = require('fs');

/**
 *Create merge files
 *
 * @param {*} CONFIG User input configuration
 */
module.exports = async CONFIG => {
  // Get the temporary directory path
  const DIRECTORY = path_join(__dirname, '../../temporary/');
  const { tools_key = [] } = CONFIG;
  let javascript = '';
  tools_key.forEach(fileN => {
    // Import method by method
    javascript += `import ${fileN}  from './${fileN}.js';
    `
  });
  const myexport = tools_key.map(String).join(',');
  // Bind to Windows
  // Derivative method
  javascript += `
  window.WT = { ${myexport} };
  export { ${myexport} };`
  // Write to temporary directory
  fs.writeFileSync(path_join(DIRECTORY, 'utils.js'), javascript);
}

Packing with webpack (webpack_build.js)

Pass in the user CONFIG configuration; identify whether to package with @babel/preset-env by -- build;
Download file packages using shell; shell npm address;
Here's a method process.cwd() to get the directory of the user's execution methods; use this as a web pack package export;

Execute webpack packaging using the configuration config/webpack.config.js file

const path = require('path');
const path_join = path.join;
const fs = require('fs');
const shell = require('shelljs');


/**
 *Check that the filename entered by the user is legitimate
 *
 * @param {*} filename file name
 * @returns file name
 */
const get_File_Name = filename => {
  if (/\.js$/.test(filename)) {
    return filename
  } else {
    return filename + '.js'
  }
}

/**
 *Packing files with webpack
 *
 * @param {*} CONFIG User Configuration
 * @returns Result
 */
module.exports = async CONFIG => {
  // configuration parameter
  const { tools_key = [], is_build = true, save_file_name } = CONFIG;
  // Get the webpack configuration address
  const CONFIG_PATH = path_join(__dirname, '../../config/');
  // Packing Output Path Address//User Open Console Address
  const OUTPUT_PATH = path_join(process.cwd(), get_File_Name(save_file_name));
  // Splicing webpack command line
  const CMD = `npx webpack ${is_build ? '--build' : ''}  --output ${OUTPUT_PATH}`;
  // Returns asynchronous results (shells are synchronous)
  return new Promise((resovle, reject) => {
    shell.cd(CONFIG_PATH);
    const EXEC_RES = shell.exec(CMD);
    if (EXEC_RES.code === 0) {
      resovle(OUTPUT_PATH); //Return the successful address
    } else {
      reject(EXEC_RES); //fail
    }
  });
};

configuration file

.babellrc

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "node": "10"
        },
        "modules": "umd",
        "useBuiltIns": "usage",
        "corejs": 3,
      }
    ]
  ],
  "plugins": [],
  "ignore": [
    "src/tools"
  ]
}

config/webpack.config.js

const path = require('path');
// Determine whether there is a -- build identifier
const IS_BUILD = (Array.isArray(process.argv) ?process.argv : []).includes('--build');
// babel
const BABEL_BUILD = {
  test: /\.js$/,
  exclude: /(node_modules|bower_components)/,//Exclude node_module directory
  use: {
    loader: 'babel-loader',
    options: {
      presets: [
        ["@babel/preset-env", {
          modules:false,
          useBuiltIns: "usage",
          corejs: 3,
        }]
      ],
      plugins: [],
    }
  }
};
module.exports = {
  entry: path.resolve(__dirname, '../temporary/utils.js'),
  mode: 'production',
  output: {
    filename: 'utils.js',
    path: path.resolve(__dirname, '../temporary/dist')
  },
  module: {
    rules: [
      (IS_BUILD ? BABEL_BUILD : {}) // --build
    ]
  }
};

bin/www

#! /usr/bin/env node
require('../src/main.js');

Publish to NPM

First modify the package.json file and add the bin attribute
The global method name is: wxh

"bin": {
  "wxh": "./bin/www"
},

Log in to your npm account

npm adduser

Push packages into npm warehouse

npm publish

Notes for pushing npm packages

  • Check if your package has been renamed in the npm Library
  • Each push package changes the version field of package.json

Write at the end

At this point, our entire package has been written, and we can use it just by installing it globally.
After routine maintenance, we just need to add one method to the src/tools directory.
Slowly write a method create_methods_list.js;
Methods According to the method files in the / src/tools directory, methods_list.json file was generated into the config directory.

const fs = require('fs');
const path = require('path');
const path_join = path.join;
const read_dir_file = require('./src/utils/read_dir_file');
// read
const fileArr = read_dir_file(path_join(__dirname, './src/tools'));
fs.writeFileSync(path_join(__dirname, './config/methods_list.json'),
  JSON.stringify({ methods_list: fileArr })
);

Keywords: Javascript npm Webpack JSON github

Added by Nicholas on Thu, 01 Aug 2019 12:14:44 +0300