For a reason

In the vue-CLI scaffolding SRC directory, there is usually an API folder where API requests are pulled out, as shown below:

The module folder contains the API extracted from each module, the axios.ts file creates an instance of axios, and adds some common configuration (such as baseURL, timeout, interceptor, etc.), and the index.ts file exposes various API methods.

Each file under Module has the same content format:

Get request parameters are a little different:

export function getSome (params? :any
) :Promise<Ajax.AjaxResponse> {
  return ax.get('/some', { params })
            .then(res= > res.data)
            .catch(error= > console.error(error))
}

Copy the code

As the project became larger and larger, there were more and more files under the Module (but the contents of the files were basically the same). As I could write less code, I had an idea: could I generate the required files through a JSON file? The diagram below:

Define a JSON file like this and execute a script that generates a file containing the following code:

Let’s get started

Our goal is simple: read a JSON file and write the values of the corresponding fields in the JSON file to a.ts file.

Here, we use node’s FS module, which reads and writes files.

// index.js
const fs = require('fs')

// Read the json file
const data = fs.readFileSync(`user.json`)

// parse imports the file
const content = JSON.parse(data)
Copy the code

Define the template for each function:

const template = item= > {
  return ` / /${item.des}\n` +
          `export function ${item.name}(params? : any)` +
          `: Promise<Ajax.AjaxResponse> {\n` +
          `  return ax.${item.method}('${item.url}', ` +
          `${item.method === 'get' ? '{ params }' : 'params'})\n` +
          ` .then(res => res.data)\n` +
          ` .catch(error => console.error)\n` +
          `}\n\n`
}
Copy the code

And then I iterate over the content

let result = "import ax from '.. /axios'\n\n"

content.forEach(item= > {
  result += template(item)
})

// Generate the file
fs.writeFileSync(`user.ts`, result)
Copy the code

Run the node index.js command to find that the attempt was successful:

In practice, there should be many modules, and the output file name should be the same as the corresponding JSON file name. It looks like this:

Let’s change the code we wrote earlier:

const fs = require('fs')
const path = require('path')

// Entry folder
const enPath = path.resolve(__dirname, '.. /src/ajax')

// Export folder
const outPath = path.resolve(__dirname, '.. /src/api/module')

// Create a directory if it does not exist
if(! fs.existsSync(outPath)) { fs.mkdirSync(outPath) }const template = item= > {
  return ` / /${item.des}\n` +
          `export function ${item.name}(params? : any)` +
          `: Promise<Ajax.AjaxResponse> {\n` +
          `  return ax.${item.method}('${item.url}', ` +
          `${item.method === 'get' ? '{ params }' : 'params'})\n` +
          ` .then(res => res.data)\n` +
          ` .catch(error => console.error)\n` +
          `}\n\n`
}


// Read the folder
const files = fs.readdirSync(enPath)

// Read a single file to generate the required file
files.forEach(file= > {
  const data = fs.readFileSync(`${enPath}/${file}`)
  const fileName = file.split('. ') [0]

  let result = ' '

  if (data.length) {
    result = "import ax from '.. /axios'\n\n"
    const content = JSON.parse(data)

    content.forEach(item= > {
      result += template(item)
    })
  }

  fs.writeFileSync(`${outPath}/${fileName}.ts`, result)
  
  console.log('Write file succeeded:${outPath}/${fileName}.ts`)})Copy the code

Execute the node index.js command, and from there, the initial goal is basically achieved.

In practice, this may not be useful, for example, some requests may require different configurations (baseURL, header, etc.), or folders may be subdivided under Ajax, etc. But, you know, you can always get out.