@anthonylzq/simba.js 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,140 @@
1
+ const writeFile = require('../utils/writeFile')
2
+
3
+ /**
4
+ * @param {String} projectName
5
+ * @returns {Promise<void>}
6
+ */
7
+ module.exports = async projectName => {
8
+ const data = {
9
+ gitignoreContent: `# Created by https://www.toptal.com/developers/gitignore/api/node,yarn
10
+ # Edit at https://www.toptal.com/developers/gitignore?templates=node,yarn
11
+
12
+ ### Node ###
13
+ # Logs
14
+ logs
15
+ *.log
16
+ npm-debug.log*
17
+ yarn-debug.log*
18
+ yarn-error.log*
19
+ lerna-debug.log*
20
+
21
+ # Diagnostic reports (https://nodejs.org/api/report.html)
22
+ report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
23
+
24
+ # Runtime data
25
+ pids
26
+ *.pid
27
+ *.seed
28
+ *.pid.lock
29
+
30
+ # Directory for instrumented libs generated by jscoverage/JSCover
31
+ lib-cov
32
+
33
+ # Coverage directory used by tools like istanbul
34
+ coverage
35
+ *.lcov
36
+
37
+ # nyc test coverage
38
+ .nyc_output
39
+
40
+ # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
41
+ .grunt
42
+
43
+ # Bower dependency directory (https://bower.io/)
44
+ bower_components
45
+
46
+ # node-waf configuration
47
+ .lock-wscript
48
+
49
+ # Compiled binary addons (https://nodejs.org/api/addons.html)
50
+ build/Release
51
+
52
+ # Dependency directories
53
+ node_modules/
54
+ jspm_packages/
55
+
56
+ # TypeScript v1 declaration files
57
+ typings/
58
+
59
+ # TypeScript cache
60
+ *.tsbuildinfo
61
+
62
+ # Optional npm cache directory
63
+ .npm
64
+
65
+ # Optional eslint cache
66
+ .eslintcache
67
+
68
+ # Microbundle cache
69
+ .rpt2_cache/
70
+ .rts2_cache_cjs/
71
+ .rts2_cache_es/
72
+ .rts2_cache_umd/
73
+
74
+ # Optional REPL history
75
+ .node_repl_history
76
+
77
+ # Output of 'npm pack'
78
+ *.tgz
79
+
80
+ # Yarn Integrity file
81
+ .yarn-integrity
82
+
83
+ # dotenv environment variables file
84
+ .env
85
+
86
+ # parcel-bundler cache (https://parceljs.org/)
87
+ .cache
88
+
89
+ # Next.js build output
90
+ .next
91
+
92
+ # Nuxt.js build / generate output
93
+ .nuxt
94
+
95
+ # Gatsby files
96
+ .cache/
97
+ # Comment in the public line in if your project uses Gatsby and not Next.js
98
+ # https://nextjs.org/blog/next-9-1#public-directory-support
99
+ # public
100
+
101
+ # vuepress build output
102
+ .vuepress/dist
103
+
104
+ # Serverless directories
105
+ .serverless/
106
+
107
+ # FuseBox cache
108
+ .fusebox/
109
+
110
+ # DynamoDB Local files
111
+ .dynamodb/
112
+
113
+ # TernJS port file
114
+ .tern-port
115
+
116
+ # Stores VSCode versions used for testing VSCode extensions
117
+ .vscode*
118
+
119
+ ### yarn ###
120
+ # https://yarnpkg.com/advanced/qa#which-files-should-be-gitignored
121
+
122
+ # .yarn/unplugged and .yarn/build-state.yml should likely always be ignored since
123
+ # they typically hold machine-specific build artifacts. Ignoring them might however
124
+ # prevent Zero-Installs from working (to prevent this, set enableScripts to false).
125
+ .yarn/unplugged
126
+ .yarn/build-state.yml
127
+
128
+ # .yarn/cache and .pnp.* may be safely ignored, but you'll need to run yarn install
129
+ # to regenerate them between each branch switch.
130
+ # Uncomment the following lines if you're not using Zero-Installs:
131
+ # .yarn/cache
132
+ # .pnp.*
133
+
134
+ # End of https://www.toptal.com/developers/gitignore/api/node,yarn
135
+ `,
136
+ gitignoreFile: '.gitignore'
137
+ }
138
+
139
+ await writeFile(`${projectName}/${data.gitignoreFile}`, data.gitignoreContent)
140
+ }
@@ -0,0 +1,16 @@
1
+ const writeFile = require('../utils/writeFile')
2
+
3
+ /**
4
+ * @param {String} projectName
5
+ * @returns {Promise<void>}
6
+ */
7
+ module.exports = async projectName => {
8
+ const data = {
9
+ herokuContent: `build:
10
+ docker:
11
+ web: Dockerfile`,
12
+ herokuFile: 'heroku.yml'
13
+ }
14
+
15
+ await writeFile(`${projectName}/${data.herokuFile}`, data.herokuContent)
16
+ }
@@ -0,0 +1,85 @@
1
+ const https = require('https')
2
+ const _ = require('underscore')
3
+ const writeFile = require('../utils/writeFile')
4
+
5
+ /**
6
+ * @param {LicenseConfig} config
7
+ * @returns {Promise<String>}
8
+ */
9
+ const getLicense = ({ author, license, year, projectDescription }) => {
10
+ return new Promise((resolve, reject) => {
11
+ https.get(`https://choosealicense.com/licenses/${license}/`, res => {
12
+ let result = ''
13
+ res.setEncoding('utf8')
14
+ res.on('data', chunk => (result += chunk))
15
+ res.on('end', () => {
16
+ const begin = result.indexOf('id="license-text"')
17
+ const end = result.indexOf('</pre>')
18
+ result = _.unescape(result.slice(begin + 18, end))
19
+
20
+ switch (license) {
21
+ case 'mit':
22
+ result = result
23
+ .replace('[year]', year)
24
+ .replace('[fullname]', author)
25
+ break
26
+ case 'apache-2.0':
27
+ result = result
28
+ .replace('[yyyy]', year)
29
+ .replace('[name of copyright owner]', author)
30
+ break
31
+ case 'gpl-3.0':
32
+ case 'agpl-3.0':
33
+ result = result
34
+ .replace('<year>', year)
35
+ .replace('<name of author>', author)
36
+ .replace(
37
+ "<one line to give the program's name and a brief idea of what it does.>",
38
+ projectDescription
39
+ )
40
+ break
41
+ }
42
+
43
+ resolve(result)
44
+ })
45
+ res.on('error', e => {
46
+ console.error(e)
47
+ reject(e)
48
+ })
49
+ })
50
+ })
51
+ }
52
+
53
+ /**
54
+ * @param {LicenseConfig} config
55
+ * @returns {Promise<Void>}
56
+ */
57
+ module.exports = async ({
58
+ author,
59
+ license,
60
+ year,
61
+ projectDescription,
62
+ projectName
63
+ }) => {
64
+ const data = {
65
+ content: '',
66
+ file: 'LICENSE'
67
+ }
68
+
69
+ data.content = await getLicense({
70
+ author,
71
+ license,
72
+ year,
73
+ projectDescription
74
+ })
75
+ await writeFile(`${projectName}/${data.file}`, data.content)
76
+ }
77
+
78
+ /**
79
+ * @typedef {Object} LicenseConfig
80
+ * @property {String} author of the project
81
+ * @property {'mit'|'apache-2.0'|'gpl-3.0'|'agpl-3.0'} license type
82
+ * @property {Number} year of the license
83
+ * @property {String} projectDescription
84
+ * @property {String} projectName
85
+ */
@@ -0,0 +1,25 @@
1
+ const writeFile = require('../utils/writeFile')
2
+
3
+ /**
4
+ * @param {String} projectName
5
+ * @returns {Promise<void>}
6
+ */
7
+ module.exports = async projectName => {
8
+ const data = {
9
+ nodemonContent: `{
10
+ "watch": [
11
+ ".env",
12
+ "src"
13
+ ],
14
+ "ext": "ts",
15
+ "ignore": [
16
+ "src/**/*.test.ts"
17
+ ],
18
+ "exec": "ts-node -r dotenv/config ./src/index"
19
+ }
20
+ `,
21
+ nodemonFile: 'nodemon.json'
22
+ }
23
+
24
+ await writeFile(`${projectName}/${data.nodemonFile}`, data.nodemonContent)
25
+ }
@@ -0,0 +1,53 @@
1
+ const writeFile = require('../utils/writeFile')
2
+
3
+ /**
4
+ * @param {PackageConfig} packageConfig
5
+ * @returns {Promise<void>}
6
+ */
7
+ module.exports = async ({
8
+ author,
9
+ projectName,
10
+ projectDescription,
11
+ projectVersion,
12
+ license,
13
+ mainFile
14
+ }) => {
15
+ const data = {
16
+ content: '',
17
+ file: 'package.json'
18
+ }
19
+
20
+ data.content = `{
21
+ "name": "${projectName.toLowerCase().replace(/ /g, '-')}",
22
+ "version": "${projectVersion}",
23
+ "main": "${mainFile}",
24
+ "description": "${projectDescription}",
25
+ "scripts": {
26
+ "build:dev": "webpack --mode development",
27
+ "build": "webpack --mode production",
28
+ "lint": "eslint src/* --ext .ts --fix",
29
+ "service": "nodemon",
30
+ "start": "node dist/index.js",
31
+ "release": "standard-version"
32
+ },
33
+ "author": "${author}",${
34
+ license !== 'unlicensed'
35
+ ? `\n "license": "${license.toUpperCase()}",\n`
36
+ : ''
37
+ }
38
+ "dependencies": {},
39
+ "devDependencies": {}
40
+ }
41
+ `
42
+ await writeFile(`${projectName}/${data.file}`, data.content)
43
+ }
44
+
45
+ /**
46
+ * @typedef {Object} PackageConfig params to create the package.json file
47
+ * @property {String} author
48
+ * @property {String} projectName
49
+ * @property {String} projectDescription
50
+ * @property {String} projectVersion
51
+ * @property {'unlicensed'|'mit'|'apache-2.0'|'mpl-2.0'|'lgpl-3.0'|'gpl-3.0'|'agpl-3.0'} license
52
+ * @property {String} mainFle
53
+ */
@@ -0,0 +1,16 @@
1
+ const writeFile = require('../utils/writeFile')
2
+ const titleCase = require('../utils/titleCase')
3
+
4
+ /**
5
+ * @param {String} projectName
6
+ * @param {String} projectDescription
7
+ * @returns {Promise<void>}
8
+ */
9
+ module.exports = async (projectName, projectDescription) => {
10
+ const data = {
11
+ readmeContent: `# ${titleCase(projectName)}\n\n${projectDescription}.\n`,
12
+ readmeFile: 'README.md'
13
+ }
14
+
15
+ await writeFile(`${projectName}/${data.readmeFile}`, data.readmeContent)
16
+ }
@@ -0,0 +1,89 @@
1
+ const writeFile = require('../utils/writeFile')
2
+
3
+ /**
4
+ * @param {String} projectName
5
+ * @returns {Promise<void>}
6
+ */
7
+ module.exports = async projectName => {
8
+ const data = {
9
+ tsconfigContent: `{
10
+ "ts-node": {
11
+ "files": true
12
+ },
13
+ "compilerOptions": {
14
+ /* Visit https://aka.ms/tsconfig.json to read more about this file */
15
+
16
+ /* Basic Options */
17
+ // "incremental": true, /* Enable incremental compilation */
18
+ "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
19
+ "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
20
+ // "lib": [], /* Specify library files to be included in the compilation. */
21
+ "allowJs": true /* Allow javascript files to be compiled. */,
22
+ // "checkJs": true, /* Report errors in .js files. */
23
+ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
24
+ // "declaration": true, /* Generates corresponding '.d.ts' file. */
25
+ // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
26
+ // "outFile": "./", /* Concatenate and emit output to single file. */
27
+ "outDir": "./dist/" /* Redirect output structure to the directory. */,
28
+ "rootDir": "./src/" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
29
+ // "composite": true, /* Enable project compilation */
30
+ // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
31
+ // "removeComments": true, /* Do not emit comments to output. */
32
+ // "noEmit": true, /* Do not emit outputs. */
33
+ // "importHelpers": true, /* Import emit helpers from 'tslib'. */
34
+ "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
35
+ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
36
+
37
+ /* Strict Type-Checking Options */
38
+ "strict": true /* Enable all strict type-checking options. */,
39
+ "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
40
+ // "strictNullChecks": true, /* Enable strict null checks. */
41
+ // "strictFunctionTypes": true, /* Enable strict checking of function types. */
42
+ // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
43
+ // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
44
+ // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
45
+ // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
46
+
47
+ /* Additional Checks */
48
+ // "noUnusedLocals": true, /* Report errors on unused locals. */
49
+ // "noUnusedParameters": true, /* Report errors on unused parameters. */
50
+ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
51
+ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
52
+
53
+ /* Module Resolution Options */
54
+ "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
55
+ // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
56
+ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
57
+ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
58
+ // "typeRoots": [], /* List of folders to include type definitions from. */
59
+ // "types": [], /* Type declaration files to be included in compilation. */
60
+ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
61
+ "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
62
+ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
63
+ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
64
+ "resolveJsonModule": true /* Allow import .json files */,
65
+
66
+ /* Source Map Options */
67
+ "sourceMap": false /* Generates corresponding '.map' file. */,
68
+ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
69
+ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
70
+ // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
71
+ // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
72
+
73
+ /* Experimental Options */
74
+ // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
75
+ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
76
+
77
+ /* Advanced Options */
78
+ "skipLibCheck": true /* Skip type checking of declaration files. */,
79
+ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
80
+ },
81
+ "include": ["./src/"],
82
+ "exclude": ["node_modules", "**/*.test.ts"]
83
+ }
84
+ `,
85
+ tsconfigFile: 'tsconfig.json'
86
+ }
87
+
88
+ await writeFile(`${projectName}/${data.tsconfigFile}`, data.tsconfigContent)
89
+ }
@@ -0,0 +1,45 @@
1
+ const writeFile = require('../utils/writeFile')
2
+
3
+ /**
4
+ * @param {String} projectName
5
+ * @returns {Promise<void>}
6
+ */
7
+ module.exports = async projectName => {
8
+ const data = {
9
+ webpackContent: `const path = require('path')
10
+ const nodeExternals = require('webpack-node-externals')
11
+
12
+ module.exports = {
13
+ context: __dirname,
14
+ entry: './src/index.ts',
15
+ externals: [nodeExternals()],
16
+ module: {
17
+ rules: [
18
+ {
19
+ exclude: /node_modules/,
20
+ test: /.ts$/,
21
+ use: {
22
+ loader: 'ts-loader'
23
+ }
24
+ }
25
+ ]
26
+ },
27
+ node: {
28
+ __dirname: false
29
+ },
30
+ resolve: {
31
+ extensions: ['.ts', '.js']
32
+ },
33
+ output: {
34
+ filename: 'index.js',
35
+ path: path.resolve(__dirname, 'dist'),
36
+ publicPath: '/dist/'
37
+ },
38
+ target: 'node'
39
+ }
40
+ `,
41
+ webpackFile: 'webpack.config.js'
42
+ }
43
+
44
+ await writeFile(`${projectName}/${data.webpackFile}`, data.webpackContent)
45
+ }
@@ -0,0 +1,161 @@
1
+ const cliProgress = require('cli-progress')
2
+ const colors = require('colors')
3
+ const util = require('util')
4
+ const exec = util.promisify(require('child_process').exec)
5
+
6
+ const packageJson = require('./functions/packageJson')
7
+ const readme = require('./functions/readme')
8
+ const changelog = require('./functions/changelog')
9
+ const licenseF = require('./functions/license')
10
+ const gitignore = require('./functions/gitignore')
11
+ const tsconfig = require('./functions/tsconfig')
12
+ const nodemon = require('./functions/nodemon')
13
+ const eslint = require('./functions/eslint')
14
+ const webpack = require('./functions/webpack')
15
+ const docker = require('./functions/docker')
16
+ const herokuF = require('./functions/heroku')
17
+ const express = require('./functions/express')
18
+
19
+ /**
20
+ * @param {Number} process number of process
21
+ * @returns {CliOptions}
22
+ */
23
+ const setOptions = process => {
24
+ const format = `${colors.bold(
25
+ 'Packages installation progress'
26
+ )} ${colors.cyan('[{bar}]')} ${colors.blue('{percentage}%')} | ${colors.bold(
27
+ 'Current process:'
28
+ )} ${colors.yellow('{value}')} of ${process} | ${colors.bold(
29
+ 'Duration:'
30
+ )} ${colors.green('{duration_formatted}')}`
31
+
32
+ return { format, hideCursor: false, synchronousUpdate: false }
33
+ }
34
+
35
+ /**
36
+ * @param {Config} config configuration to build the project
37
+ */
38
+ module.exports = async ({
39
+ author,
40
+ email,
41
+ projectName,
42
+ projectDescription,
43
+ heroku,
44
+ license,
45
+ version,
46
+ licenseYear,
47
+ manager,
48
+ mainFile
49
+ }) => {
50
+ const process = 4
51
+ let i = 0
52
+
53
+ const options = setOptions(process)
54
+ const bar = new cliProgress.SingleBar(
55
+ options,
56
+ cliProgress.Presets.shades_classic
57
+ )
58
+
59
+ const prodPackages = `${manager} express mongoose morgan http-errors joi swagger-ui-express`
60
+ const devPackages = `${manager} -D \
61
+ @types/node \
62
+ @typescript-eslint/eslint-plugin \
63
+ @typescript-eslint/parser \
64
+ dotenv \
65
+ eslint \
66
+ eslint-config-prettier \
67
+ eslint-config-standard \
68
+ eslint-plugin-import \
69
+ eslint-plugin-prettier \
70
+ eslint-plugin-sort-keys-fix \
71
+ eslint-plugin-typescript-sort-keys \
72
+ nodemon \
73
+ prettier \
74
+ ts-loader \
75
+ ts-node \
76
+ typescript \
77
+ webpack \
78
+ webpack-cli \
79
+ webpack-node-externals \
80
+ @types/express \
81
+ @types/morgan \
82
+ @types/swagger-ui-express \
83
+ @types/http-errors \
84
+ standard-version`
85
+
86
+ bar.start(process, i)
87
+
88
+ try {
89
+ await exec(`mkdir ${projectName}`)
90
+ bar.update(++i)
91
+
92
+ const functions = [
93
+ packageJson({
94
+ author: `${author} <${email}>`,
95
+ projectName,
96
+ projectDescription,
97
+ projectVersion: version,
98
+ license,
99
+ mainFile
100
+ }),
101
+ readme(projectName, projectDescription),
102
+ changelog(projectName),
103
+ gitignore(projectName),
104
+ tsconfig(projectName),
105
+ nodemon(projectName),
106
+ eslint(projectName),
107
+ webpack(projectName),
108
+ docker(projectName),
109
+ express(projectName, version, email),
110
+ exec('git init', { cwd: `./${projectName}` })
111
+ ]
112
+
113
+ if (license !== 'unlicensed')
114
+ functions.push(
115
+ licenseF({
116
+ author,
117
+ license,
118
+ year: licenseYear,
119
+ projectDescription,
120
+ projectName
121
+ })
122
+ )
123
+
124
+ if (heroku) functions.push(herokuF(projectName))
125
+
126
+ await Promise.all(functions)
127
+ bar.update(++i)
128
+
129
+ await exec(prodPackages, { cwd: `./${projectName}` })
130
+ bar.update(++i)
131
+
132
+ await exec(devPackages, { cwd: `./${projectName}` })
133
+ bar.update(++i)
134
+
135
+ bar.stop()
136
+ } catch (e) {
137
+ console.error(e)
138
+ }
139
+ }
140
+
141
+ /**
142
+ * @typedef {Object} Config configuration to initialize a project
143
+ * @property {String} author author of the project
144
+ * @property {String} email email of the project author
145
+ * @property {String} projectName project name
146
+ * @property {String} projectDescription project description
147
+ * @property {Boolean} heroku true if the project will be deployed in heroku
148
+ * @property {'unlicensed'|'mit'|'apache-2.0'|'mpl-2.0'|'lgpl-3.0'|'gpl-3.0'|'agpl-3.0'} license project license
149
+ * @property {String} version project initial version
150
+ * @property {String} licenseYear year when the license starts in format YYYY
151
+ * @property {Boolean} npm true means that the package manager will be npm, otherwise yarn
152
+ * @property {'yarn add'|'npm i'} manager command that will be used to install packages
153
+ * @property {String} mainFile main file of the project
154
+ */
155
+
156
+ /**
157
+ * @typedef {Object} CliOptions
158
+ * @property {String} format cli format to show the progress to the user
159
+ * @property {Boolean} hideCursor
160
+ * @property {Boolean} synchronousUpdate
161
+ */
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @param {String} projectName
3
+ * @returns {String}
4
+ */
5
+ module.exports = projectName => {
6
+ const pn = projectName.toLowerCase().split('-')
7
+ let title = ''
8
+
9
+ pn.forEach((word, index, array) => {
10
+ title += `${word[0].toUpperCase()}${word.slice(1)} `
11
+
12
+ if (index !== array.length - 1) title += ' '
13
+ })
14
+
15
+ return title
16
+ }
@@ -0,0 +1,15 @@
1
+ const fs = require('fs')
2
+
3
+ /**
4
+ * @param {String} filename
5
+ * @param {String} data
6
+ * @returns {Promise<String>}
7
+ */
8
+ module.exports = (filename, data) => {
9
+ return new Promise((resolve, reject) => {
10
+ fs.writeFile(filename, data, error => {
11
+ if (error) reject(error.message)
12
+ else resolve('Saved successfully')
13
+ })
14
+ })
15
+ }