@vamship/build-utils 1.0.0-0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,47 @@
1
+ 'use strict';
2
+
3
+ const _gulp = require('gulp');
4
+
5
+ /**
6
+ * Sub builder that creates a task that will copy type declaration files that
7
+ * have been marked for export from source to build directories. This method
8
+ * will return a watcher if the watch option is set to true.
9
+ *
10
+ * @private
11
+ * @param {Object} project Reference to an object that contains project metadata
12
+ * that can be used to customize build outputs.
13
+ * @param {Object} options An options object that can be used to customize the
14
+ * task.
15
+ *
16
+ * @returns {Function} A gulp task.
17
+ */
18
+ module.exports = (project, options) => {
19
+ const { watch } = Object.assign({ watch: false }, options);
20
+ const rootDir = project.rootDir;
21
+ const workingDir = rootDir.getChild('working');
22
+
23
+ const paths = [project.exportedTypes]
24
+ .map((dir) => rootDir.getChild(dir))
25
+ .map((dir) => [undefined].map((ext) => dir.getAllFilesGlob(ext)))
26
+ .reduce((result, arr) => result.concat(arr), []);
27
+ console.log('building types');
28
+
29
+ const task = () =>
30
+ _gulp
31
+ .src(paths, { allowEmpty: true, base: rootDir.globPath })
32
+ .pipe(_gulp.dest(workingDir.absolutePath));
33
+
34
+ task.displayName = 'build-types';
35
+ task.description =
36
+ 'Copy type declaration files from source to build directory';
37
+
38
+ if (watch) {
39
+ const watchTask = () => _gulp.watch(paths, task);
40
+ watchTask.displayName = 'watch-build-types';
41
+ watchTask.description =
42
+ 'Automatically copy type declaration files to build directory on change';
43
+
44
+ return watchTask;
45
+ }
46
+ return task;
47
+ };
@@ -0,0 +1,52 @@
1
+ 'use strict';
2
+
3
+ const _gulp = require('gulp');
4
+
5
+ /**
6
+ * Builder function that can be used to generate a gulp task to build source
7
+ * files. The task takes on different implementations based on project types.
8
+ * For example, this task will compile typescript projects, copy AWS
9
+ * microservice projects to the target directory, and has no effect on other
10
+ * pure javascript projects.
11
+ *
12
+ * @param {Object} project Reference to an object that contains project metadata
13
+ * that can be used to customize build outputs.
14
+ * @param {Object} options An options object that can be used to customize the
15
+ * task.
16
+ *
17
+ * @returns {Function} A gulp task.
18
+ */
19
+ module.exports = (project, options) => {
20
+ const { watch } = Object.assign({ watch: false }, options);
21
+
22
+ if (
23
+ !project.hasExportedTypes &&
24
+ !project.hasTypescript &&
25
+ project.projectType !== 'aws-microservice'
26
+ ) {
27
+ return;
28
+ }
29
+
30
+ const jsBuild = require('./build-js');
31
+ const tasks = [jsBuild(project, options)];
32
+
33
+ if (project.hasTypescript) {
34
+ const tsBuild = require('./build-ts');
35
+ tasks.push(tsBuild(project, options));
36
+ } else if (project.hasExportedTypes) {
37
+ const typesBuild = require('./build-types');
38
+ tasks.push(typesBuild(project, options));
39
+ }
40
+
41
+ const task = _gulp.parallel(tasks);
42
+ if (!watch) {
43
+ task.displayName = 'build';
44
+ task.description = 'Transpile/copy source files into working directory';
45
+ } else {
46
+ task.displayName = 'watch-build';
47
+ task.description =
48
+ 'Automatically transpile/copy source files on change';
49
+ }
50
+
51
+ return task;
52
+ };
@@ -0,0 +1,57 @@
1
+ 'use strict';
2
+
3
+ const _delete = require('delete');
4
+
5
+ /**
6
+ * Builder function that can be used to generate a gulp task to clean temporary
7
+ * project files.
8
+ *
9
+ * @param {Object} project Reference to an object that contains project metadata
10
+ * that can be used to customize build outputs.
11
+ * @param {Object} options An options object that can be used to customize the
12
+ * task.
13
+ *
14
+ * @returns {Function} A gulp task.
15
+ */
16
+ module.exports = (project, options) => {
17
+ const rootDir = project.rootDir;
18
+
19
+ const dirs = ['coverage', 'dist'];
20
+ const extras = [];
21
+
22
+ if (
23
+ project.hasExportedTypes ||
24
+ project.hasTypescript ||
25
+ project.projectType === 'aws-microservice'
26
+ ) {
27
+ dirs.push('working');
28
+ }
29
+
30
+ if (project.hasTypescript) {
31
+ dirs.push('.tscache');
32
+ extras.push({
33
+ name: 'typescript-temp',
34
+ path: rootDir.getFileGlob('tscommand-*.tmp.txt'),
35
+ });
36
+ }
37
+
38
+ if (project.projectType === 'aws-microservice') {
39
+ dirs.push('cdk.out');
40
+ }
41
+
42
+ if (project.hasServer) {
43
+ extras.push({
44
+ name: 'logs',
45
+ path: rootDir.getChild('logs').getAllFilesGlob('log'),
46
+ });
47
+ }
48
+
49
+ const paths = dirs.map((dir) => rootDir.getChild(dir).globPath);
50
+ const task = () => _delete(paths);
51
+
52
+ task.displayName = 'clean';
53
+ task.description =
54
+ 'Cleans out working, distribution and temporary files and directories';
55
+
56
+ return task;
57
+ };
@@ -0,0 +1,41 @@
1
+ 'use strict';
2
+
3
+ const _gulp = require('gulp');
4
+ const _gulpJsdoc = require('gulp-jsdoc3');
5
+
6
+ /**
7
+ * Sub builder that creates a task that will generate documentation from
8
+ * javascript files.
9
+ *
10
+ * @private
11
+ * @param {Object} project Reference to an object that contains project metadata
12
+ * that can be used to customize build outputs.
13
+ * @param {Object} options An options object that can be used to customize the
14
+ * task.
15
+ *
16
+ * @returns {Function} A gulp task.
17
+ */
18
+ module.exports = (project, options) => {
19
+ const { rootDir, name, version } = project;
20
+
21
+ const docOptions = Object.assign(
22
+ {
23
+ opts: {
24
+ readme: rootDir.getFilePath('README.md'),
25
+ destination: rootDir.getFilePath(`docs/${name}/${version}`),
26
+ template: rootDir.getFilePath('node_modules/docdash'),
27
+ },
28
+ },
29
+ options
30
+ );
31
+
32
+ const paths = ['src']
33
+ .map((dir) => rootDir.getChild(dir))
34
+ .map((dir) => ['js'].map((ext) => dir.getAllFilesGlob(ext)))
35
+ .reduce((result, arr) => result.concat(arr), []);
36
+
37
+ const task = () =>
38
+ _gulp.src(paths, { allowEmpty: true }).pipe(_gulpJsdoc(docOptions));
39
+
40
+ return task;
41
+ };
@@ -0,0 +1,40 @@
1
+ 'use strict';
2
+
3
+ const _gulp = require('gulp');
4
+ const _gulpTypedoc = require('gulp-typedoc');
5
+
6
+ /**
7
+ * Sub builder that creates a task that will generate documentation from
8
+ * typescript files.
9
+ *
10
+ * @private
11
+ * @param {Object} project Reference to an object that contains project metadata
12
+ * that can be used to customize build outputs.
13
+ * @param {Object} options An options object that can be used to customize the
14
+ * task.
15
+ *
16
+ * @returns {Function} A gulp task.
17
+ */
18
+ module.exports = (project, options) => {
19
+ const { rootDir, name, version } = project;
20
+
21
+ const docOptions = Object.assign(
22
+ {
23
+ name: `${name} Documentation`,
24
+ disableOutputCheck: true,
25
+ readme: rootDir.getFilePath('README.md'),
26
+ out: rootDir.getFilePath(`docs/${name}/${version}`),
27
+ },
28
+ options
29
+ );
30
+
31
+ const paths = ['src']
32
+ .map((dir) => rootDir.getChild(dir))
33
+ .map((dir) => ['ts'].map((ext) => dir.getAllFilesGlob(ext)))
34
+ .reduce((result, arr) => result.concat(arr), []);
35
+
36
+ const task = () =>
37
+ _gulp.src(paths, { allowEmpty: true }).pipe(_gulpTypedoc(docOptions));
38
+
39
+ return task;
40
+ };
@@ -0,0 +1,32 @@
1
+ 'use strict';
2
+
3
+ const _gulp = require('gulp');
4
+
5
+ /**
6
+ * Builder function that can be used to generate a gulp task that generates
7
+ * documentation from code docs. The task takes on different implementations
8
+ * based on the programming language - javascript or typescript.
9
+ *
10
+ * @param {Object} project Reference to an object that contains project metadata
11
+ * that can be used to customize build outputs.
12
+ * @param {Object} options An options object that can be used to customize the
13
+ * task.
14
+ *
15
+ * @returns {Function} A gulp task.
16
+ */
17
+ module.exports = (project, options) => {
18
+ let createTask = null;
19
+
20
+ if (project.hasTypescript) {
21
+ createTask = require('./docs-ts');
22
+ } else {
23
+ createTask = require('./docs-js');
24
+ }
25
+
26
+ const task = createTask(project, options);
27
+
28
+ task.displayName = 'docs';
29
+ task.description = 'Generates project documentation from code docs';
30
+
31
+ return task;
32
+ };
@@ -0,0 +1,56 @@
1
+ 'use strict';
2
+
3
+ const _gulp = require('gulp');
4
+ const _prettier = require('gulp-prettier');
5
+
6
+ /**
7
+ * Builder function that can be used to generate a gulp task to format source
8
+ * files.
9
+ *
10
+ * @param {Object} project Reference to an object that contains project metadata
11
+ * that can be used to customize build outputs.
12
+ * @param {Object} options An options object that can be used to customize the
13
+ * task.
14
+ *
15
+ * @returns {Function} A gulp task.
16
+ */
17
+ module.exports = (project, options) => {
18
+ const { watch } = Object.assign({ watch: false }, options);
19
+
20
+ const rootDir = project.rootDir;
21
+
22
+ const dirs = ['src', 'test', '.gulp'];
23
+ const extras = ['Gulpfile.js', 'README.md'];
24
+
25
+ if (project.projectType === 'aws-microservice') {
26
+ dirs.push('infra');
27
+ }
28
+
29
+ const paths = dirs
30
+ .map((dir) => rootDir.getChild(dir))
31
+ .map((dir) =>
32
+ ['ts', 'js', 'json', 'py'].map((ext) => dir.getAllFilesGlob(ext))
33
+ )
34
+ .reduce((result, arr) => result.concat(arr), [])
35
+ .concat(extras.map((file) => rootDir.getFileGlob(file)));
36
+
37
+ const task = () =>
38
+ _gulp
39
+ .src(paths, { allowEmpty: true, base: rootDir.globPath })
40
+ .pipe(_prettier())
41
+ .pipe(_gulp.dest(rootDir.absolutePath));
42
+
43
+ task.displayName = 'format';
44
+ task.description = 'Formats all source files, README.md and build scripts';
45
+
46
+ if (watch) {
47
+ const watch = () =>
48
+ _gulp.watch(paths, { usePolling: true, delay: 5000 }, task);
49
+
50
+ watch.displayName = 'watch-format';
51
+ watch.description = 'Automatically format files on change';
52
+
53
+ return watch;
54
+ }
55
+ return task;
56
+ };
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * A collection of task builder functions that can be used to generate gulp
5
+ * tasks based on project configuration.
6
+ */
7
+ module.exports = [
8
+ 'clean',
9
+ 'format',
10
+ 'lint',
11
+ 'build',
12
+ 'test',
13
+ 'docs',
14
+ 'package',
15
+ 'publish',
16
+ ].reduce((tasks, task) => {
17
+ tasks[task] = require(`./${task}`);
18
+ return tasks;
19
+ }, {});
@@ -0,0 +1,56 @@
1
+ 'use strict';
2
+
3
+ const _gulp = require('gulp');
4
+ const _eslint = require('gulp-eslint');
5
+
6
+ /**
7
+ * Builder function that can be used to generate a gulp task to format source
8
+ * files.
9
+ *
10
+ * @param {Object} project Reference to an object that contains project metadata
11
+ * that can be used to customize build outputs.
12
+ * @param {Object} options An options object that can be used to customize the
13
+ * task.
14
+ *
15
+ * @returns {Function} A gulp task.
16
+ */
17
+ module.exports = (project, options) => {
18
+ const { watch } = Object.assign({ watch: false }, options);
19
+
20
+ const rootDir = project.rootDir;
21
+ const extensions = ['js'];
22
+ const dirs = ['src', 'test'];
23
+
24
+ if (project.hasTypescript) {
25
+ extensions.push('ts');
26
+ }
27
+
28
+ if (project.projectType === 'aws-microservice') {
29
+ dirs.push('infra');
30
+ }
31
+
32
+ const paths = dirs
33
+ .map((dir) => rootDir.getChild(dir))
34
+ .map((dir) => extensions.map((ext) => dir.getAllFilesGlob(ext)))
35
+ .reduce((result, arr) => result.concat(arr), []);
36
+
37
+ const task = () =>
38
+ _gulp
39
+ .src(paths, { allowEmpty: true })
40
+ .pipe(_eslint())
41
+ .pipe(_eslint.format())
42
+ .pipe(_eslint.failAfterError());
43
+
44
+ task.displayName = 'lint';
45
+ task.description = 'Lints source files';
46
+
47
+ if (watch) {
48
+ return task;
49
+ } else {
50
+ const watchTask = () => _gulp.watch(paths, task);
51
+ watchTask.displayName = 'watch-lint';
52
+ watchTask.description = 'Automatically lint files on change';
53
+
54
+ return watchTask;
55
+ }
56
+ };
@@ -0,0 +1,50 @@
1
+ 'use strict';
2
+
3
+ const _gulp = require('gulp');
4
+
5
+ /**
6
+ * Builder function that can be used to generate a gulp task to package a
7
+ * project for distribution. The task takes on different implementations based
8
+ * on project types. For example, javascript libraries will yield an archive
9
+ * resulting from an `npm pack`, while docker enabled projects will result in
10
+ * the creation of a docker image.
11
+ *
12
+ * @param {Object} project Reference to an object that contains project metadata
13
+ * that can be used to customize build outputs.
14
+ * @param {Object} options An options object that can be used to customize the
15
+ * task.
16
+ *
17
+ * @returns {Function} A gulp task.
18
+ */
19
+ module.exports = (project, options) => {
20
+ const { types } = options;
21
+ let createTask = null;
22
+
23
+ if (types) {
24
+ if (!project.hasExportedTypes) {
25
+ return;
26
+ }
27
+ createTask = require('./package-types');
28
+ } else if (project.projectType === 'aws-microservice') {
29
+ createTask = require('./package-aws');
30
+ } else if (project.hasDocker) {
31
+ createTask = require('./package-docker');
32
+ } else if (project.projectType === 'lib' || project.projectType === 'cli') {
33
+ createTask = require('./package-npm');
34
+ }
35
+
36
+ const task = createTask(project, options);
37
+
38
+ if (!(task instanceof Array)) {
39
+ if (types) {
40
+ task.displayName = 'package-types';
41
+ task.description =
42
+ 'Create a distribution package for the types exported by the project';
43
+ } else {
44
+ task.displayName = 'package';
45
+ task.description = 'Create a distribution package for the project';
46
+ }
47
+ }
48
+
49
+ return task;
50
+ };
@@ -0,0 +1,58 @@
1
+ 'use strict';
2
+
3
+ const _gulp = require('gulp');
4
+ const _zip = require('gulp-zip');
5
+ const _execa = require('execa');
6
+
7
+ /**
8
+ * Sub builder that packages an aws-microservice project for deployment. This
9
+ * follows the build steps described for
10
+ * [lambda deployments](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-create-deployment-pkg.html#nodejs-package-dependencies)
11
+ *
12
+ * @private
13
+ * @param {Object} project Reference to an object that contains project metadata
14
+ * that can be used to customize build outputs.
15
+ * @param {Object} options An options object that can be used to customize the
16
+ * task.
17
+ *
18
+ * @returns {Function} A gulp task.
19
+ */
20
+ module.exports = (project, options) => {
21
+ const { snakeCasedName, version, rootDir } = project;
22
+ const workingDir = rootDir.getChild('working');
23
+
24
+ const packageName = `${snakeCasedName}-${version}.zip`;
25
+
26
+ const installTask = () => {
27
+ const npmBin = 'npm';
28
+ const args = ['install', '--production'];
29
+
30
+ return _execa(npmBin, args, {
31
+ stdio: 'inherit',
32
+ cwd: workingDir.absolutePath,
33
+ });
34
+ };
35
+
36
+ installTask.displayName = 'package-aws-install';
37
+ installTask.description = 'Install package dependency in working directory';
38
+
39
+ const dirs = ['src', 'node_modules'];
40
+ const extras = ['package.json', project.configFileName];
41
+
42
+ const paths = dirs
43
+ .map((dir) => workingDir.getChild(dir))
44
+ .map((dir) => dir.getAllFilesGlob())
45
+ .concat(extras.map((file) => workingDir.getFileGlob(file)));
46
+
47
+ const zipTask = () =>
48
+ _gulp
49
+ .src(paths, { allowEmpty: true, base: workingDir.globPath })
50
+ .pipe(_zip(packageName))
51
+ .pipe(_gulp.dest(rootDir.getChild('dist').absolutePath));
52
+
53
+ zipTask.displayName = 'package-aws-zip';
54
+ zipTask.description =
55
+ 'Create a project distribution for AWS lambda deployments';
56
+
57
+ return _gulp.series([installTask, zipTask]);
58
+ };
@@ -0,0 +1,128 @@
1
+ 'use strict';
2
+
3
+ const _execa = require('execa');
4
+ const _gulp = require('gulp');
5
+ const _log = require('fancy-log');
6
+ const _mkdirp = require('mkdirp');
7
+
8
+ /**
9
+ * Sub builder that builds a docker image based on a predefined dockerfile.
10
+ *
11
+ * @private
12
+ * @param {Object} project Reference to an object that contains project metadata
13
+ * that can be used to customize build outputs.
14
+ * @param {Object} options An options object that can be used to customize the
15
+ * task.
16
+ *
17
+ * @returns {Function} A gulp task.
18
+ */
19
+ module.exports = (project, options) => {
20
+ const {
21
+ unscopedName,
22
+ version,
23
+ description,
24
+ configFileName,
25
+ jsRootDir,
26
+ rootDir,
27
+ } = project;
28
+
29
+ const dockerBin = 'docker';
30
+
31
+ const tasks = project.getDockerTargets().map((target) => {
32
+ const { name, buildFile, buildArgs, isDeprecated, isDefault } = target;
33
+
34
+ const suffix = isDefault ? '' : `-${name}`;
35
+ const targetName = isDefault ? '' : name;
36
+
37
+ let repo = target.repo;
38
+ if (typeof process.env.BUILD_DOCKER_REPO !== 'undefined') {
39
+ repo = process.env.BUILD_DOCKER_REPO;
40
+ _log.warn(`Docker repo override specified: [${repo}]`);
41
+ }
42
+
43
+ if (isDeprecated) {
44
+ _log.warn(
45
+ '[WARNING] Docker package task configuration is deprecated. Please upgrade to the newer format'
46
+ );
47
+ _log.warn(
48
+ '[WARNING] See: https://github.com/vamship/build-utils#upgrading-to-v03x for more information'
49
+ );
50
+ }
51
+
52
+ const buildTaskArgs = [
53
+ 'build',
54
+ '--rm',
55
+ '--file',
56
+ buildFile,
57
+ '--tag',
58
+ `${repo}:latest`,
59
+ '--build-arg',
60
+ `APP_NAME=${unscopedName}`,
61
+ '--build-arg',
62
+ `APP_VERSION=${version}`,
63
+ '--build-arg',
64
+ `APP_DESCRIPTION='${description}'`,
65
+ '--build-arg',
66
+ `CONFIG_FILE_NAME=${configFileName}`,
67
+ '--build-arg',
68
+ `BUILD_TIMESTAMP=${Date.now()}`,
69
+ ];
70
+
71
+ project.validateRequiredEnv();
72
+ buildArgs.forEach(({ name, value }) => {
73
+ buildTaskArgs.push('--build-arg');
74
+ buildTaskArgs.push(`${name}=${value}`);
75
+ });
76
+
77
+ buildTaskArgs.push('.');
78
+
79
+ const buildTask = () =>
80
+ _execa(dockerBin, buildTaskArgs, {
81
+ stdio: 'inherit',
82
+ cwd: jsRootDir.absolutePath,
83
+ });
84
+ buildTask.displayName = `package-build${suffix}`;
85
+ buildTask.description = `Builds a docker image (${targetName}) based on the Dockerfile contained in the project`;
86
+
87
+ const tasks = [buildTask];
88
+
89
+ if (process.env.BUILD_EXPORT_DOCKER_IMAGE === 'true') {
90
+ _log.warn(`Docker save image enabled.`);
91
+
92
+ const distDir = rootDir.getChild('dist');
93
+ const savePath = distDir.getFilePath(`image${suffix}.tar`);
94
+
95
+ const ensureDirTask = () => {
96
+ _log.info(
97
+ `Ensuring that output path exists: ${distDir.absolutePath}`
98
+ );
99
+ return _mkdirp(distDir.absolutePath);
100
+ };
101
+ ensureDirTask.displayName = `package-save${suffix}`;
102
+ ensureDirTask.description = `Ensures that destination directory (${savePath}) exists.`;
103
+ tasks.push(ensureDirTask);
104
+
105
+ const saveTask = () => {
106
+ _log.info(
107
+ `Docker save enabled. File will be created at: ${savePath}`
108
+ );
109
+ return _execa(dockerBin, ['save', '--output', savePath, repo], {
110
+ stdio: 'inherit',
111
+ cwd: jsRootDir.absolutePath,
112
+ });
113
+ };
114
+ saveTask.displayName = `package-save${suffix}`;
115
+ ensureDirTask.description = `Saves a tar file that represents the docker image`;
116
+ tasks.push(saveTask);
117
+ }
118
+
119
+ const task = _gulp.series(tasks);
120
+
121
+ task.displayName = `package${suffix}`;
122
+ task.description = `Builds a docker image (${targetName}) based on the Dockerfile contained in the project`;
123
+
124
+ return task;
125
+ });
126
+
127
+ return tasks;
128
+ };
@@ -0,0 +1,25 @@
1
+ 'use strict';
2
+
3
+ const { createNpmPackageTask } = require('./utils');
4
+
5
+ /**
6
+ * Sub builder that packages a project using npm pack, from source files or
7
+ * compiled typescript files.
8
+ *
9
+ * @private
10
+ * @param {Object} project Reference to an object that contains project metadata
11
+ * that can be used to customize build outputs.
12
+ * @param {Object} options An options object that can be used to customize the
13
+ * task.
14
+ *
15
+ * @returns {Function} A gulp task.
16
+ */
17
+ module.exports = (project, options) => {
18
+ const { snakeCasedName, version, rootDir, jsRootDir } = project;
19
+
20
+ const packageName = `${snakeCasedName}-${version}.tgz`;
21
+ const packageDir = jsRootDir;
22
+ const distDir = rootDir.getChild('dist');
23
+
24
+ return createNpmPackageTask(packageDir, packageName, distDir);
25
+ };