@vamship/build-utils 1.6.1 → 2.0.0-2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. package/package.json +41 -40
  2. package/src/directory.js +20 -24
  3. package/src/index.js +5 -17
  4. package/src/project.js +160 -433
  5. package/src/schema/project-definition.js +137 -0
  6. package/src/task-builder.js +100 -0
  7. package/src/task-builders/build-js-task-builder.js +57 -0
  8. package/src/task-builders/build-task-builder.js +78 -0
  9. package/src/task-builders/build-ts-task-builder.js +63 -0
  10. package/src/task-builders/build-ui-task-builder.js +45 -0
  11. package/src/task-builders/clean-task-builder.js +39 -0
  12. package/src/task-builders/copy-files-task-builder.js +78 -0
  13. package/src/task-builders/docs-js-task-builder.js +74 -0
  14. package/src/task-builders/docs-task-builder.js +74 -0
  15. package/src/task-builders/docs-ts-task-builder.js +52 -0
  16. package/src/task-builders/format-task-builder.js +61 -0
  17. package/src/task-builders/index.js +21 -17
  18. package/src/task-builders/lint-fix-task-builder.js +61 -0
  19. package/src/task-builders/lint-task-builder.js +56 -0
  20. package/src/task-builders/not-supported-task-builder.js +48 -0
  21. package/src/task-builders/package-aws-task-builder.js +105 -0
  22. package/src/task-builders/package-container-task-builder.js +132 -0
  23. package/src/task-builders/package-npm-task-builder.js +83 -0
  24. package/src/task-builders/package-task-builder.js +101 -0
  25. package/src/task-builders/publish-aws-task-builder.js +111 -0
  26. package/src/task-builders/publish-container-task-builder.js +103 -0
  27. package/src/task-builders/publish-npm-task-builder.js +60 -0
  28. package/src/task-builders/publish-task-builder.js +98 -0
  29. package/src/task-builders/test-task-builder.js +85 -0
  30. package/src/task-builders/test-ui-task-builder.js +65 -0
  31. package/src/task-builders/watch-task-builder.js +109 -0
  32. package/src/task-factories/api-task-factory.js +67 -0
  33. package/src/task-factories/aws-microservice-task-factory.js +53 -0
  34. package/src/task-factories/cli-task-factory.js +68 -0
  35. package/src/task-factories/container-task-factory.js +64 -0
  36. package/src/task-factories/index.js +8 -0
  37. package/src/task-factories/lib-task-factory.js +52 -0
  38. package/src/task-factories/ui-task-factory.js +48 -0
  39. package/src/task-factory.js +52 -0
  40. package/src/utils/semver-utils.js +29 -0
  41. package/src/utils/task-factory-utils.js +70 -0
  42. package/src/task-builders/build/build-js.js +0 -66
  43. package/src/task-builders/build/build-ts.js +0 -70
  44. package/src/task-builders/build/build-types.js +0 -47
  45. package/src/task-builders/build/build-ui.js +0 -67
  46. package/src/task-builders/build/index.js +0 -60
  47. package/src/task-builders/clean.js +0 -57
  48. package/src/task-builders/docs/docs-js.js +0 -41
  49. package/src/task-builders/docs/docs-ts.js +0 -40
  50. package/src/task-builders/docs/index.js +0 -32
  51. package/src/task-builders/format.js +0 -58
  52. package/src/task-builders/lint.js +0 -56
  53. package/src/task-builders/package/index.js +0 -50
  54. package/src/task-builders/package/package-aws.js +0 -58
  55. package/src/task-builders/package/package-docker.js +0 -128
  56. package/src/task-builders/package/package-npm.js +0 -25
  57. package/src/task-builders/package/package-types.js +0 -54
  58. package/src/task-builders/package/utils.js +0 -50
  59. package/src/task-builders/publish/index.js +0 -50
  60. package/src/task-builders/publish/publish-aws.js +0 -62
  61. package/src/task-builders/publish/publish-docker.js +0 -79
  62. package/src/task-builders/publish/publish-npm.js +0 -36
  63. package/src/task-builders/publish/publish-types.js +0 -36
  64. package/src/task-builders/test/index.js +0 -39
  65. package/src/task-builders/test/test-ui.js +0 -39
  66. package/src/task-builders/test/test.js +0 -67
@@ -0,0 +1,74 @@
1
+ 'use strict';
2
+
3
+ import _gulp from 'gulp';
4
+ import TaskBuilder from '../task-builder.js';
5
+ import { Project } from '../project.js';
6
+ import { NotSupportedTaskBuilder } from './not-supported-task-builder.js';
7
+ import { DocsJsTaskBuilder } from './docs-js-task-builder.js';
8
+ import { DocsTsTaskBuilder } from './docs-ts-task-builder.js';
9
+
10
+ /**
11
+ * General purpose build task that configures sub tasks for build based on the
12
+ * project.
13
+ */
14
+ export class DocsTaskBuilder extends TaskBuilder {
15
+ /**
16
+ * Creates a new task builder.
17
+ */
18
+ constructor() {
19
+ super(
20
+ 'docs',
21
+ `Generates documentation from code comments in source files`,
22
+ );
23
+ }
24
+
25
+ /**
26
+ * Generates a gulp task to package a project for building a project.
27
+ *
28
+ * @protected
29
+ * @param {Object} project Reference to the project for which the task needs
30
+ * to be defined.
31
+ *
32
+ * @returns {Function} A gulp task.
33
+ */
34
+ _createTask(project) {
35
+ if (!(project instanceof Project)) {
36
+ throw new Error('Invalid project (arg #1)');
37
+ }
38
+
39
+ const builders = this._getSubBuilders(project).map((builder) =>
40
+ builder.buildTask(project),
41
+ );
42
+
43
+ const task = _gulp.series(builders);
44
+ return task;
45
+ }
46
+
47
+ /**
48
+ * Returns a list of sub builders based on the project type and language.
49
+ * @private
50
+ */
51
+ _getSubBuilders(project) {
52
+ const { type, language } = project;
53
+ if (type === 'container') {
54
+ return [new NotSupportedTaskBuilder()];
55
+ } else if (language === 'ts') {
56
+ return [new DocsTsTaskBuilder()];
57
+ } else {
58
+ return [new DocsJsTaskBuilder()];
59
+ }
60
+ }
61
+
62
+ /**
63
+ * @override
64
+ */
65
+ getWatchPaths(project) {
66
+ if (!(project instanceof Project)) {
67
+ throw new Error('Invalid project (arg #1)');
68
+ }
69
+ const paths = this._getSubBuilders(project)
70
+ .map((builder) => builder.getWatchPaths(project))
71
+ .flat();
72
+ return [...new Set(paths)];
73
+ }
74
+ }
@@ -0,0 +1,52 @@
1
+ import { execa as _execa } from 'execa';
2
+
3
+ import TaskBuilder from '../task-builder.js';
4
+ import { Project } from '../project.js';
5
+
6
+ /**
7
+ * Builder that can be used to generate a gulp task to generate documentation
8
+ * from code comments in typescript files.
9
+ */
10
+ export class DocsTsTaskBuilder extends TaskBuilder {
11
+ /**
12
+ * Creates a new task builder.
13
+ */
14
+ constructor() {
15
+ super(
16
+ 'docs-ts',
17
+ 'Generates documentation from code comments in typescript files',
18
+ );
19
+ }
20
+
21
+ /**
22
+ * Generates a gulp task to generate documentation from code comments in
23
+ * source code.
24
+ *
25
+ * @protected
26
+ * @param {Object} project Reference to the project for which the task needs
27
+ * to be defined.
28
+ *
29
+ * @returns {Function} A gulp task.
30
+ */
31
+ _createTask(project) {
32
+ if (!(project instanceof Project)) {
33
+ throw new Error('Invalid project (arg #1)');
34
+ }
35
+
36
+ const { rootDir } = project;
37
+ const docsDir = rootDir.getChild('docs').getFilePath(project.version);
38
+ const srcDir = rootDir.getChild('src');
39
+
40
+ const task = () =>
41
+ _execa('typedoc', ['--out', docsDir, srcDir.absolutePath], {
42
+ stdio: 'inherit',
43
+ }).then(undefined, (err) => {
44
+ /*
45
+ * Do nothing. This handler prevents the gulp task from
46
+ * crashing with an unhandled error.
47
+ */
48
+ console.error(err);
49
+ });
50
+ return task;
51
+ }
52
+ }
@@ -0,0 +1,61 @@
1
+ import _gulp from 'gulp';
2
+ import _prettier from 'gulp-prettier';
3
+
4
+ import TaskBuilder from '../task-builder.js';
5
+ import { Project } from '../project.js';
6
+
7
+ /**
8
+ * Builder that can be used to generate a gulp task to format source/test files.
9
+ */
10
+ export class FormatTaskBuilder extends TaskBuilder {
11
+ /**
12
+ * Creates a new task builder.
13
+ */
14
+ constructor() {
15
+ super(
16
+ 'format',
17
+ 'Formats all source files, README.md and build scripts',
18
+ );
19
+ }
20
+
21
+ /**
22
+ * Generates a gulp task to format source files.
23
+ *
24
+ * @protected
25
+ * @param {Object} project Reference to the project for which the task needs
26
+ * to be defined.
27
+ *
28
+ * @returns {Function} A gulp task.
29
+ */
30
+ _createTask(project) {
31
+ if (!(project instanceof Project)) {
32
+ throw new Error('Invalid project (arg #1)');
33
+ }
34
+
35
+ const dirs = ['src', 'test', 'infra', '.gulp'];
36
+ const extras = ['Gulpfile.js', 'README.md'];
37
+ const extensions = ['ts', 'js', 'json', 'py', 'tsx', 'jsx'];
38
+
39
+ const paths = dirs
40
+ .map((dir) => project.rootDir.getChild(dir))
41
+ .map((dir) => extensions.map((ext) => dir.getAllFilesGlob(ext)))
42
+ .reduce((result, arr) => result.concat(arr), [])
43
+ .concat(extras.map((file) => project.rootDir.getFileGlob(file)));
44
+
45
+ const task = () =>
46
+ _gulp
47
+ .src(paths, {
48
+ allowEmpty: true,
49
+ base: project.rootDir.globPath,
50
+ })
51
+ .pipe(_prettier())
52
+ .on('error', (err) => {
53
+ /*
54
+ * Do nothing. This handler prevents the gulp task from
55
+ * crashing with an unhandled error.
56
+ */
57
+ })
58
+ .pipe(_gulp.dest(project.rootDir.absolutePath));
59
+ return task;
60
+ }
61
+ }
@@ -1,19 +1,23 @@
1
1
  'use strict';
2
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
- }, {});
3
+ export * from './build-js-task-builder.js';
4
+ export * from './build-ts-task-builder.js';
5
+ export * from './build-ui-task-builder.js';
6
+ export * from './clean-task-builder.js';
7
+ export * from './copy-files-task-builder.js';
8
+ export * from './docs-js-task-builder.js';
9
+ export * from './docs-ts-task-builder.js';
10
+ export * from './format-task-builder.js';
11
+ export * from './lint-fix-task-builder.js';
12
+ export * from './lint-task-builder.js';
13
+ export * from './package-aws-task-builder.js';
14
+ export * from './package-container-task-builder.js';
15
+ export * from './package-npm-task-builder.js';
16
+ export * from './publish-aws-task-builder.js';
17
+ export * from './publish-container-task-builder.js';
18
+ export * from './publish-npm-task-builder.js';
19
+ export * from './test-task-builder.js';
20
+ export * from './test-ui-task-builder.js';
21
+ export * from './watch-task-builder.js';
22
+ export * from './build-task-builder.js';
23
+ export * from './not-supported-task-builder.js';
@@ -0,0 +1,61 @@
1
+ 'use strict';
2
+
3
+ import _gulp from 'gulp';
4
+ import _eslint from 'gulp-eslint-new';
5
+
6
+ import TaskBuilder from '../task-builder.js';
7
+ import { Project } from '../project.js';
8
+
9
+ /**
10
+ * Builder that can be used to generate a gulp task to lint source/test files,
11
+ * and implement any automatic fixes that are possible.
12
+ */
13
+ export class LintFixTaskBuilder extends TaskBuilder {
14
+ /**
15
+ * Creates a new task builder.
16
+ */
17
+ constructor() {
18
+ super(
19
+ 'lint-fix',
20
+ 'Lints all source files and applies automatic fixes where possible',
21
+ );
22
+ }
23
+
24
+ /**
25
+ * Generates a gulp task to clean up temporary project files.
26
+ *
27
+ * @protected
28
+ * @param {Object} project Reference to the project for which the task needs
29
+ * to be defined.
30
+ *
31
+ * @returns {Function} A gulp task.
32
+ */
33
+ _createTask(project) {
34
+ if (!(project instanceof Project)) {
35
+ throw new Error('Invalid project (arg #1)');
36
+ }
37
+
38
+ const dirs = ['src', 'test', 'infra', '.gulp'];
39
+ const extras = ['Gulpfile.js'];
40
+ const extensions = ['ts', 'js', 'tsx', 'jsx'];
41
+
42
+ const paths = dirs
43
+ .map((dir) => project.rootDir.getChild(dir))
44
+ .map((dir) => extensions.map((ext) => dir.getAllFilesGlob(ext)))
45
+ .reduce((result, arr) => result.concat(arr), [])
46
+ .concat(extras.map((file) => project.rootDir.getFileGlob(file)));
47
+
48
+ const task = () =>
49
+ _gulp
50
+ .src(paths, {
51
+ allowEmpty: true,
52
+ base: project.rootDir.globPath,
53
+ })
54
+ .pipe(_eslint({ configType: 'flat', fix: true }))
55
+ .pipe(_eslint.fix())
56
+ .pipe(_eslint.format())
57
+ .pipe(_eslint.failAfterError());
58
+
59
+ return task;
60
+ }
61
+ }
@@ -0,0 +1,56 @@
1
+ 'use strict';
2
+
3
+ import _gulp from 'gulp';
4
+ import _eslint from 'gulp-eslint-new';
5
+
6
+ import TaskBuilder from '../task-builder.js';
7
+ import { Project } from '../project.js';
8
+
9
+ /**
10
+ * Builder that can be used to generate a gulp task to lint source/test files.
11
+ */
12
+ export class LintTaskBuilder extends TaskBuilder {
13
+ /**
14
+ * Creates a new task builder.
15
+ */
16
+ constructor() {
17
+ super('lint', 'Lints all source files');
18
+ }
19
+
20
+ /**
21
+ * Generates a gulp task to lint project files.
22
+ *
23
+ * @protected
24
+ * @param {Object} project Reference to the project for which the task needs
25
+ * to be defined.
26
+ *
27
+ * @returns {Function} A gulp task.
28
+ */
29
+ _createTask(project) {
30
+ if (!(project instanceof Project)) {
31
+ throw new Error('Invalid project (arg #1)');
32
+ }
33
+
34
+ const dirs = ['src', 'test', 'infra', '.gulp'];
35
+ const extras = ['Gulpfile.js'];
36
+ const extensions = ['ts', 'js', 'tsx', 'jsx'];
37
+
38
+ const paths = dirs
39
+ .map((dir) => project.rootDir.getChild(dir))
40
+ .map((dir) => extensions.map((ext) => dir.getAllFilesGlob(ext)))
41
+ .reduce((result, arr) => result.concat(arr), [])
42
+ .concat(extras.map((file) => project.rootDir.getFileGlob(file)));
43
+
44
+ const task = () =>
45
+ _gulp
46
+ .src(paths, {
47
+ allowEmpty: true,
48
+ base: project.rootDir.globPath,
49
+ })
50
+ .pipe(_eslint({ configType: 'flat' }))
51
+ .pipe(_eslint.format())
52
+ .pipe(_eslint.failAfterError());
53
+
54
+ return task;
55
+ }
56
+ }
@@ -0,0 +1,48 @@
1
+ 'use strict';
2
+
3
+ import _fancyLog from 'fancy-log';
4
+ import TaskBuilder from '../task-builder.js';
5
+ import { Project } from '../project.js';
6
+
7
+ /**
8
+ * Task builder that creates a task that displays a "not supported" message on
9
+ * the screen. Intended to indicate that the task does not apply for the
10
+ * specific project type.
11
+ */
12
+ export class NotSupportedTaskBuilder extends TaskBuilder {
13
+ /**
14
+ * Creates a new task builder.
15
+ */
16
+ constructor() {
17
+ super(
18
+ 'not-supported',
19
+ `Task that does nothing - used to indicate that a task is not supported for a project type.`,
20
+ );
21
+ }
22
+
23
+ /**
24
+ * Generates a gulp task to package a project for building a project.
25
+ *
26
+ * @protected
27
+ * @param {Object} project Reference to the project for which the task needs
28
+ * to be defined.
29
+ *
30
+ * @returns {Function} A gulp task.
31
+ */
32
+ _createTask(project) {
33
+ if (!(project instanceof Project)) {
34
+ throw new Error('Invalid project (arg #1)');
35
+ }
36
+ return () => _fancyLog.warn('Task not defined for project');
37
+ }
38
+
39
+ /**
40
+ * @override
41
+ */
42
+ getWatchPaths(project) {
43
+ if (!(project instanceof Project)) {
44
+ throw new Error('Invalid project (arg #1)');
45
+ }
46
+ return [];
47
+ }
48
+ }
@@ -0,0 +1,105 @@
1
+ 'use strict';
2
+
3
+ import TaskBuilder from '../task-builder.js';
4
+ import { Project } from '../project.js';
5
+ import { execa as _execa } from 'execa';
6
+ import _gulp from 'gulp';
7
+ import _zip from 'gulp-zip';
8
+
9
+ /**
10
+ * Builder function that can be used to generate a gulp task to package a
11
+ * project for deployment to AWS.
12
+ */
13
+ export class PackageAwsTaskBuilder extends TaskBuilder {
14
+ /**
15
+ * Creates a new task builder.
16
+ */
17
+ constructor() {
18
+ super('package-aws', `Package a project for publishing to AWS`);
19
+ }
20
+
21
+ /**
22
+ * Generates a gulp task to package a project for deployment to AWS.
23
+ *
24
+ * @protected
25
+ * @param {Object} project Reference to the project for which the task needs
26
+ * to be defined.
27
+ *
28
+ * @returns {Function} A gulp task.
29
+ */
30
+ _createTask(project) {
31
+ if (!(project instanceof Project)) {
32
+ throw new Error('Invalid project (arg #1)');
33
+ }
34
+
35
+ const jsDir =
36
+ project.language === 'js'
37
+ ? project.rootDir
38
+ : project.rootDir.getChild('working');
39
+
40
+ const installTask = () => {
41
+ const npmBin = 'npm';
42
+ const args = ['install', '--production'];
43
+
44
+ return _execa(npmBin, args, {
45
+ stdio: 'inherit',
46
+ cwd: jsDir.absolutePath,
47
+ }).then(undefined, (err) => {
48
+ /*
49
+ * Do nothing. This handler prevents the gulp task from
50
+ * crashing with an unhandled error.
51
+ */
52
+ });
53
+ };
54
+
55
+ const dirs = ['src', 'node_modules'];
56
+ const extras = ['package.json', project.configFileName];
57
+
58
+ const paths = dirs
59
+ .map((dir) => jsDir.getChild(dir))
60
+ .map((dir) => dir.getAllFilesGlob())
61
+ .concat(extras.map((file) => jsDir.getFileGlob(file)));
62
+ const packageName = `${project.kebabCasedName}-${project.version}.zip`;
63
+
64
+ const zipTask = () =>
65
+ _gulp
66
+ .src(paths, {
67
+ allowEmpty: true,
68
+ base: project.rootDir.globPath,
69
+ })
70
+ .pipe(_zip(packageName))
71
+ .on('error', (err) => {
72
+ /*
73
+ * Do nothing. This handler prevents the gulp task from
74
+ * crashing with an unhandled error.
75
+ */
76
+ })
77
+ .pipe(
78
+ _gulp.dest(project.rootDir.getChild('dist').absolutePath),
79
+ );
80
+
81
+ const task = _gulp.series([installTask, zipTask]);
82
+ return task;
83
+ }
84
+
85
+ /**
86
+ * @override
87
+ */
88
+ getWatchPaths(project) {
89
+ if (!(project instanceof Project)) {
90
+ throw new Error('Invalid project (arg #1)');
91
+ }
92
+ const dirs = ['src', 'test', 'infra'];
93
+ const exts = ['md', 'html', 'json', 'js', 'jsx', 'ts', 'tsx'];
94
+ const rootDir =
95
+ project.language === 'ts'
96
+ ? project.rootDir.getChild('working')
97
+ : project.rootDir;
98
+
99
+ return dirs
100
+ .map((dir) =>
101
+ exts.map((ext) => rootDir.getChild(dir).getAllFilesGlob(ext)),
102
+ )
103
+ .flat();
104
+ }
105
+ }
@@ -0,0 +1,132 @@
1
+ 'use strict';
2
+
3
+ import TaskBuilder from '../task-builder.js';
4
+ import { Project } from '../project.js';
5
+ import { execa as _execa } from 'execa';
6
+
7
+ /**
8
+ * Builder function that can be used to generate a gulp task to package a
9
+ * container project for publishing to a container registry.
10
+ */
11
+ export class PackageContainerTaskBuilder extends TaskBuilder {
12
+ /**
13
+ * Creates a new task builder.
14
+ *
15
+ * @param {String} target The name of the container build target
16
+ * @param {String} [repo=undefined] The name of the container repo
17
+ */
18
+ constructor(target, repo) {
19
+ if (typeof target !== 'string' || target.length === 0) {
20
+ throw new Error('Invalid target (arg #1)');
21
+ }
22
+ if (
23
+ typeof repo !== 'undefined' &&
24
+ (typeof repo !== 'string' || repo.length === 0)
25
+ ) {
26
+ throw new Error('Invalid repo (arg #2)');
27
+ }
28
+
29
+ super(
30
+ // When specifying the container target, if it is not called default, this
31
+ // will create a named task
32
+ `package-container${target === 'default' ? '' : '-' + target}`,
33
+ `Package a project for publishing to a container registry`,
34
+ );
35
+ this._target = target;
36
+ this._repo = repo;
37
+ }
38
+
39
+ /**
40
+ * Generates a gulp task to package a container image
41
+ *
42
+ * @protected
43
+ * @param {Object} project Reference to the project for which the task needs
44
+ * to be defined.
45
+ *
46
+ * @returns {Function} A gulp task.
47
+ */
48
+ _createTask(project) {
49
+ if (!(project instanceof Project)) {
50
+ throw new Error('Invalid project (arg #1)');
51
+ }
52
+
53
+ const undefinedVars = project.getUndefinedEnvironmentVariables();
54
+ if (undefinedVars.length > 0) {
55
+ throw new Error(
56
+ `Missing required environment variables: [${undefinedVars.join(
57
+ ', ',
58
+ )}]`,
59
+ );
60
+ }
61
+
62
+ const jsDir =
63
+ project.language === 'js'
64
+ ? project.rootDir
65
+ : project.rootDir.getChild('working');
66
+ const definition = project.getContainerDefinition(this._target);
67
+
68
+ const repo =
69
+ typeof this._repo === 'undefined' ? definition.repo : this._repo;
70
+ const { buildFile, buildArgs } = definition;
71
+
72
+ const dockerBin = 'docker';
73
+ const args = [
74
+ 'build',
75
+ '--rm',
76
+ '--file',
77
+ buildFile,
78
+ '--tag',
79
+ `${repo}:latest`,
80
+ '--build-arg',
81
+ `APP_NAME=${project.unscopedName}`,
82
+ '--build-arg',
83
+ `APP_VERSION=${project.version}`,
84
+ '--build-arg',
85
+ `APP_DESCRIPTION='${project.description}'`,
86
+ '--build-arg',
87
+ `CONFIG_FILE_NAME=${project.configFileName}`,
88
+ '--build-arg',
89
+ `BUILD_TIMESTAMP=${Date.now()}`,
90
+ ];
91
+
92
+ Object.keys(buildArgs).forEach((key) => {
93
+ args.push('--build-arg');
94
+ args.push(`${key}=${buildArgs[key]}`);
95
+ });
96
+
97
+ args.push('.');
98
+
99
+ const task = () =>
100
+ _execa(dockerBin, args, {
101
+ stdio: 'inherit',
102
+ cwd: jsDir.absolutePath,
103
+ }).then(undefined, (err) => {
104
+ /*
105
+ * Do nothing. This handler prevents the gulp task from
106
+ * crashing with an unhandled error.
107
+ */
108
+ });
109
+ return task;
110
+ }
111
+
112
+ /**
113
+ * @override
114
+ */
115
+ getWatchPaths(project) {
116
+ if (!(project instanceof Project)) {
117
+ throw new Error('Invalid project (arg #1)');
118
+ }
119
+ const dirs = ['src', 'test', 'infra'];
120
+ const exts = ['md', 'html', 'json', 'js', 'jsx', 'ts', 'tsx'];
121
+ const rootDir =
122
+ project.language === 'ts'
123
+ ? project.rootDir.getChild('working')
124
+ : project.rootDir;
125
+
126
+ return dirs
127
+ .map((dir) =>
128
+ exts.map((ext) => rootDir.getChild(dir).getAllFilesGlob(ext)),
129
+ )
130
+ .flat();
131
+ }
132
+ }