@vamship/build-utils 1.6.1 → 2.0.0-1

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.
Files changed (66) hide show
  1. package/package.json +40 -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,83 @@
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 _delete from 'delete';
8
+
9
+ /**
10
+ * Builder function that can be used to generate a gulp task to package an
11
+ * project for publishing to an NPM registry.
12
+ */
13
+ export class PackageNpmTaskBuilder extends TaskBuilder {
14
+ /**
15
+ * Creates a new task builder.
16
+ */
17
+ constructor() {
18
+ super('package-npm', `Package a project for publishing to NPM`);
19
+ }
20
+
21
+ /**
22
+ * Generates a gulp task to execute automated tests
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 packageName = `${project.kebabCasedName}-${project.version}.tgz`;
36
+ const jsDir =
37
+ project.language === 'js'
38
+ ? project.rootDir
39
+ : project.rootDir.getChild('working');
40
+ const srcPath = jsDir.getFilePath(packageName);
41
+ const distDir = project.rootDir.getChild('dist');
42
+
43
+ const npmBin = 'npm';
44
+ const packTask = () =>
45
+ _execa(npmBin, ['pack'], {
46
+ stdio: 'inherit',
47
+ cwd: jsDir.absolutePath,
48
+ }).then(undefined, (err) => {
49
+ /*
50
+ * Do nothing. This handler prevents the gulp task from
51
+ * crashing with an unhandled error.
52
+ */
53
+ });
54
+
55
+ const copyTask = () =>
56
+ _gulp.src(srcPath).pipe(_gulp.dest(distDir.absolutePath));
57
+ const deleteTask = () => _delete([srcPath]);
58
+
59
+ const task = _gulp.series([packTask, copyTask, deleteTask]);
60
+ return task;
61
+ }
62
+
63
+ /**
64
+ * @override
65
+ */
66
+ getWatchPaths(project) {
67
+ if (!(project instanceof Project)) {
68
+ throw new Error('Invalid project (arg #1)');
69
+ }
70
+ const dirs = ['src', 'test', 'infra'];
71
+ const exts = ['md', 'html', 'json', 'js', 'jsx', 'ts', 'tsx'];
72
+ const rootDir =
73
+ project.language === 'ts'
74
+ ? project.rootDir.getChild('working')
75
+ : project.rootDir;
76
+
77
+ return dirs
78
+ .map((dir) =>
79
+ exts.map((ext) => rootDir.getChild(dir).getAllFilesGlob(ext)),
80
+ )
81
+ .flat();
82
+ }
83
+ }
@@ -0,0 +1,101 @@
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 { PackageAwsTaskBuilder } from './package-aws-task-builder.js';
8
+ import { PackageNpmTaskBuilder } from './package-npm-task-builder.js';
9
+ import { PackageContainerTaskBuilder } from './package-container-task-builder.js';
10
+
11
+ /**
12
+ * General purpose packaging task that configures sub tasks for packaging based
13
+ * on the project. When a project is an API or container and has multiple container
14
+ * targets, this task will package the target named "default". When the project is
15
+ * a CLI and there is a "default" container defined, this task will package that,
16
+ * if there is no container defined, it will package using npm.
17
+ */
18
+ export class PackageTaskBuilder extends TaskBuilder {
19
+ /**
20
+ * Creates a new task builder.
21
+ */
22
+ constructor() {
23
+ super(
24
+ 'package',
25
+ `Packages project build files for publishing to a repository`,
26
+ );
27
+ }
28
+
29
+ /**
30
+ * Generates a gulp task to package a project for packaging a project.
31
+ *
32
+ * @protected
33
+ * @param {Object} project Reference to the project for which the task needs
34
+ * to be defined.
35
+ *
36
+ * @returns {Function} A gulp task.
37
+ */
38
+ _createTask(project) {
39
+ if (!(project instanceof Project)) {
40
+ throw new Error('Invalid project (arg #1)');
41
+ }
42
+
43
+ const builders = this._getSubBuilders(project).map((builder) =>
44
+ builder.buildTask(project),
45
+ );
46
+
47
+ const task = _gulp.series(builders);
48
+ return task;
49
+ }
50
+
51
+ /**
52
+ * Returns a list of sub builders based on the project type and language.
53
+ * @private
54
+ */
55
+ _getSubBuilders(project) {
56
+ const { type } = project;
57
+ const containerTargetList = project.getContainerTargets();
58
+
59
+ // Type lib
60
+ if (type === 'lib') {
61
+ return [new PackageNpmTaskBuilder()];
62
+ }
63
+ // Type aws-microservice
64
+ else if (type === 'aws-microservice') {
65
+ return [new PackageAwsTaskBuilder()];
66
+ }
67
+ // Type container
68
+ else if (type === 'container') {
69
+ return [new PackageContainerTaskBuilder('default')];
70
+ }
71
+ // Type cli
72
+ else if (type === 'cli') {
73
+ if (containerTargetList.length > 0) {
74
+ return [new PackageContainerTaskBuilder('default')];
75
+ } else {
76
+ return [new PackageNpmTaskBuilder()];
77
+ }
78
+ }
79
+ // Type api
80
+ else if (type === 'api') {
81
+ return [new PackageContainerTaskBuilder('default')];
82
+ }
83
+ // Type ui (and potentially others that are not supported)
84
+ else {
85
+ return [new NotSupportedTaskBuilder()];
86
+ }
87
+ }
88
+
89
+ /**
90
+ * @override
91
+ */
92
+ getWatchPaths(project) {
93
+ if (!(project instanceof Project)) {
94
+ throw new Error('Invalid project (arg #1)');
95
+ }
96
+ const paths = this._getSubBuilders(project)
97
+ .map((builder) => builder.getWatchPaths(project))
98
+ .flat();
99
+ return [...new Set(paths)];
100
+ }
101
+ }
@@ -0,0 +1,111 @@
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 { config as _dotenvConfig } from 'dotenv';
7
+ import _dotenvExpand from 'dotenv-expand';
8
+
9
+ /**
10
+ * Builder function that can be used to generate a gulp task to publish a CDK
11
+ * project to AWS.
12
+ */
13
+ export class PublishAwsTaskBuilder extends TaskBuilder {
14
+ /**
15
+ * Creates a new task builder.
16
+ *
17
+ * @param {String} target The name of the CDK stack target
18
+ * @param {String} environment The name of the environment to use for
19
+ * sourcing environment variables.
20
+ * @param {Boolean} requireApproval A flag that indicates whether or not the
21
+ * publish task requires interactive approval from the user.
22
+ */
23
+ constructor(target, environment, requireApproval) {
24
+ if (typeof target !== 'string' || target.length === 0) {
25
+ throw new Error('Invalid target (arg #1)');
26
+ }
27
+ if (typeof environment !== 'string' || environment.length === 0) {
28
+ throw new Error('Invalid environment (arg #2)');
29
+ }
30
+ if (typeof requireApproval !== 'boolean') {
31
+ throw new Error('Invalid requireApproval (arg #3)');
32
+ }
33
+ super('publish-aws', `Publish a CDK project to AWS`);
34
+
35
+ this._target = target;
36
+ this._environment = environment;
37
+ this._requireApproval = requireApproval;
38
+ }
39
+
40
+ /**
41
+ * Generates a gulp task to execute automated tests
42
+ *
43
+ * @protected
44
+ * @param {Object} project Reference to the project for which the task needs
45
+ * to be defined.
46
+ *
47
+ * @returns {Function} A gulp task.
48
+ */
49
+ _createTask(project) {
50
+ if (!(project instanceof Project)) {
51
+ throw new Error('Invalid project (arg #1)');
52
+ }
53
+
54
+ const definition = project.getCdkStackDefinition(this._target);
55
+ const infraDir = project.rootDir.getChild('infra');
56
+ const jsDir =
57
+ project.language === 'js'
58
+ ? project.rootDir
59
+ : project.rootDir.getChild('working');
60
+
61
+ const task = () => {
62
+ [`.env.${this._environment}`, '.env']
63
+ .map((envFile) => infraDir.getFileGlob(envFile))
64
+ .forEach((envFile) => {
65
+ _dotenvExpand(_dotenvConfig(envFile));
66
+ });
67
+
68
+ const undefinedVars = project.getUndefinedEnvironmentVariables();
69
+ if (undefinedVars.length > 0) {
70
+ throw new Error(
71
+ `Missing required environment variables: [${undefinedVars.join(
72
+ ',',
73
+ )}]`,
74
+ );
75
+ }
76
+
77
+ const cdkBin = 'cdk';
78
+ const args = [
79
+ 'deploy',
80
+ definition.name,
81
+ '--app',
82
+ jsDir.getChild('infra').getFilePath('index'),
83
+ ];
84
+
85
+ if (this._requireApproval) {
86
+ args.splice(1, 0, '--require-approval=never');
87
+ }
88
+
89
+ _execa(cdkBin, args, {
90
+ stdio: 'inherit',
91
+ cwd: jsDir.absolutePath,
92
+ }).then(undefined, (err) => {
93
+ /*
94
+ * Do nothing. This handler prevents the gulp task from
95
+ * crashing with an unhandled error.
96
+ */
97
+ });
98
+ };
99
+ return task;
100
+ }
101
+
102
+ /**
103
+ * @override
104
+ */
105
+ getWatchPaths(project) {
106
+ if (!(project instanceof Project)) {
107
+ throw new Error('Invalid project (arg #1)');
108
+ }
109
+ return [];
110
+ }
111
+ }
@@ -0,0 +1,103 @@
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 { getSemverComponents } from '../utils/semver-utils.js';
8
+
9
+ /**
10
+ * Builder function that can be used to generate a gulp task to publish a CDK
11
+ * project to CONTAINER.
12
+ */
13
+ export class PublishContainerTaskBuilder extends TaskBuilder {
14
+ /**
15
+ * Creates a new task builder.
16
+ *
17
+ * @param {String} target The name of the CDK stack target
18
+ * @param {String} [tag='latest'] An optional tag to apply to the container
19
+ * image.
20
+ */
21
+ constructor(target, tag = 'latest') {
22
+ if (typeof target !== 'string' || target.length === 0) {
23
+ throw new Error('Invalid target (arg #1)');
24
+ }
25
+ if (
26
+ typeof tag !== 'undefined' &&
27
+ (typeof tag !== 'string' || tag.length === 0)
28
+ ) {
29
+ throw new Error('Invalid tag (arg #2)');
30
+ }
31
+ super(
32
+ // When specifying the container target, if it is not called default, this
33
+ // will create a named task
34
+ `publish-container${target === 'default' ? '' : '-' + target}`,
35
+ `Publish container image for ${target}:${tag}`,
36
+ );
37
+
38
+ this._target = target;
39
+ this._tag = tag;
40
+ }
41
+
42
+ /**
43
+ * Generates a gulp task to execute automated tests
44
+ *
45
+ * @protected
46
+ * @param {Object} project Reference to the project for which the task needs
47
+ * to be defined.
48
+ *
49
+ * @returns {Function} A gulp task.
50
+ */
51
+ _createTask(project) {
52
+ if (!(project instanceof Project)) {
53
+ throw new Error('Invalid project (arg #1)');
54
+ }
55
+
56
+ const definition = project.getContainerDefinition(this._target);
57
+
58
+ const semverComponents = getSemverComponents(this._tag);
59
+ const tagTaskList = semverComponents.map((tag) => {
60
+ const tagTask = () =>
61
+ // Per docker docs `docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]`
62
+ _execa(
63
+ 'docker',
64
+ ['tag', definition.name, `${definition.name}:${tag}`],
65
+ {
66
+ stdio: 'inherit',
67
+ },
68
+ ).then(undefined, (err) => {
69
+ /*
70
+ * Do nothing. This handler prevents the gulp task from
71
+ * crashing with an unhandled error.
72
+ */
73
+ });
74
+ return tagTask;
75
+ });
76
+ const pushTaskList = semverComponents.map((tag) => {
77
+ const pushTask = () =>
78
+ // Per docker docs `docker push [OPTIONS] NAME[:TAG]`
79
+ _execa('docker', ['push', `${definition.name}:${tag}`], {
80
+ stdio: 'inherit',
81
+ }).then(undefined, (err) => {
82
+ /*
83
+ * Do nothing. This handler prevents the gulp task from
84
+ * crashing with an unhandled error.
85
+ */
86
+ });
87
+ return pushTask;
88
+ });
89
+
90
+ const task = _gulp.series([...tagTaskList, ...pushTaskList]);
91
+ return task;
92
+ }
93
+
94
+ /**
95
+ * @override
96
+ */
97
+ getWatchPaths(project) {
98
+ if (!(project instanceof Project)) {
99
+ throw new Error('Invalid project (arg #1)');
100
+ }
101
+ return [];
102
+ }
103
+ }
@@ -0,0 +1,60 @@
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 publish an
9
+ * already packaged project to an NPM registry.
10
+ */
11
+ export class PublishNpmTaskBuilder extends TaskBuilder {
12
+ /**
13
+ * Creates a new task builder.
14
+ */
15
+ constructor() {
16
+ super('publish-npm', `Publish a project to an NPM registry`);
17
+ }
18
+
19
+ /**
20
+ * Generates a gulp task to execute automated tests
21
+ *
22
+ * @protected
23
+ * @param {Object} project Reference to the project for which the task needs
24
+ * to be defined.
25
+ *
26
+ * @returns {Function} A gulp task.
27
+ */
28
+ _createTask(project) {
29
+ if (!(project instanceof Project)) {
30
+ throw new Error('Invalid project (arg #1)');
31
+ }
32
+
33
+ const packageName = `${project.kebabCasedName}-${project.version}.tgz`;
34
+ const distDir = project.rootDir.getChild('dist');
35
+
36
+ const npmBin = 'npm';
37
+ const task = () =>
38
+ _execa(npmBin, ['publish', packageName], {
39
+ stdio: 'inherit',
40
+ cwd: distDir.absolutePath,
41
+ }).then(undefined, (err) => {
42
+ /*
43
+ * Do nothing. This handler prevents the gulp task from
44
+ * crashing with an unhandled error.
45
+ */
46
+ });
47
+
48
+ return task;
49
+ }
50
+
51
+ /**
52
+ * @override
53
+ */
54
+ getWatchPaths(project) {
55
+ if (!(project instanceof Project)) {
56
+ throw new Error('Invalid project (arg #1)');
57
+ }
58
+ return [];
59
+ }
60
+ }
@@ -0,0 +1,98 @@
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 { PublishAwsTaskBuilder } from './publish-aws-task-builder.js';
8
+ import { PublishNpmTaskBuilder } from './publish-npm-task-builder.js';
9
+ import { PublishContainerTaskBuilder } from './publish-container-task-builder.js';
10
+
11
+ /**
12
+ * General purpose publishing task that configures sub tasks for publishing based
13
+ * on the project. When a project is an API or container and has multiple container
14
+ * targets, this task will publish the target named "default". When the project is
15
+ * a CLI and there is a "default" container defined, this task will publish that,
16
+ * if there is no container defined, it will publish using npm.
17
+ */
18
+ export class PublishTaskBuilder extends TaskBuilder {
19
+ /**
20
+ * Creates a new task builder.
21
+ */
22
+ constructor() {
23
+ super('publish', `Publishes project to a repository`);
24
+ }
25
+
26
+ /**
27
+ * Generates a gulp task to publish a project.
28
+ *
29
+ * @protected
30
+ * @param {Object} project Reference to the project for which the task needs
31
+ * to be defined.
32
+ *
33
+ * @returns {Function} A gulp task.
34
+ */
35
+ _createTask(project) {
36
+ if (!(project instanceof Project)) {
37
+ throw new Error('Invalid project (arg #1)');
38
+ }
39
+
40
+ const builders = this._getSubBuilders(project).map((builder) =>
41
+ builder.buildTask(project),
42
+ );
43
+
44
+ const task = _gulp.series(builders);
45
+ return task;
46
+ }
47
+
48
+ /**
49
+ * Returns a list of sub builders based on the project type and language.
50
+ * @private
51
+ */
52
+ _getSubBuilders(project) {
53
+ const { type } = project;
54
+ const containerTargetList = project.getContainerTargets();
55
+
56
+ // Type lib
57
+ if (type === 'lib') {
58
+ return [new PublishNpmTaskBuilder()];
59
+ }
60
+ // Type aws-microservice
61
+ else if (type === 'aws-microservice') {
62
+ return [new PublishAwsTaskBuilder()];
63
+ }
64
+ // Type container
65
+ else if (type === 'container') {
66
+ return [new PublishContainerTaskBuilder('default')];
67
+ }
68
+ // Type cli
69
+ else if (type === 'cli') {
70
+ if (containerTargetList.length > 0) {
71
+ return [new PublishContainerTaskBuilder('default')];
72
+ } else {
73
+ return [new PublishNpmTaskBuilder()];
74
+ }
75
+ }
76
+ // Type api
77
+ else if (type === 'api') {
78
+ return [new PublishContainerTaskBuilder('default')];
79
+ }
80
+ // Type ui (and potentially others that are not supported)
81
+ else {
82
+ return [new NotSupportedTaskBuilder()];
83
+ }
84
+ }
85
+
86
+ /**
87
+ * @override
88
+ */
89
+ getWatchPaths(project) {
90
+ if (!(project instanceof Project)) {
91
+ throw new Error('Invalid project (arg #1)');
92
+ }
93
+ const paths = this._getSubBuilders(project)
94
+ .map((builder) => builder.getWatchPaths(project))
95
+ .flat();
96
+ return [...new Set(paths)];
97
+ }
98
+ }
@@ -0,0 +1,85 @@
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 execute
9
+ * instrumented unit/api tests.
10
+ */
11
+ export class TestTaskBuilder extends TaskBuilder {
12
+ /**
13
+ * Creates a new task builder.
14
+ *
15
+ * @param {String} testType The type of test to execute. Must be one of
16
+ * "unit" or "api".
17
+ */
18
+ constructor(testType) {
19
+ if (['unit', 'api'].indexOf(testType) < 0) {
20
+ throw new Error('Invalid testType (arg #1)');
21
+ }
22
+ super(`test-${testType}`, `Execute ${testType} tests`);
23
+
24
+ this._testType = testType;
25
+ }
26
+
27
+ /**
28
+ * Generates a gulp task to execute automated tests
29
+ *
30
+ * @protected
31
+ * @param {Object} project Reference to the project for which the task needs
32
+ * to be defined.
33
+ *
34
+ * @returns {Function} A gulp task.
35
+ */
36
+ _createTask(project) {
37
+ if (!(project instanceof Project)) {
38
+ throw new Error('Invalid project (arg #1)');
39
+ }
40
+ const mochaBin = project.rootDir.getFilePath('node_modules/.bin/mocha');
41
+ const c8Bin = project.rootDir.getFilePath('node_modules/.bin/c8');
42
+ const jsRootDir =
43
+ project.language === 'ts'
44
+ ? project.rootDir.getChild('working')
45
+ : project.rootDir;
46
+
47
+ const args = [
48
+ '-x {working/,}test/**',
49
+ mochaBin,
50
+ '--no-config',
51
+ '--loader=esmock',
52
+ jsRootDir.getChild(`test/${this._testType}`).getAllFilesGlob('js'),
53
+ ];
54
+
55
+ const task = () =>
56
+ _execa(c8Bin, args, { stdio: 'inherit' }).then(undefined, () => {
57
+ /*
58
+ * Do nothing. This handler prevents the gulp task from
59
+ * crashing with an unhandled error.
60
+ */
61
+ });
62
+ return task;
63
+ }
64
+
65
+ /**
66
+ * @override
67
+ */
68
+ getWatchPaths(project) {
69
+ if (!(project instanceof Project)) {
70
+ throw new Error('Invalid project (arg #1)');
71
+ }
72
+ const dirs = ['src', 'test', 'infra'];
73
+ const exts = ['md', 'html', 'json', 'js', 'jsx', 'ts', 'tsx'];
74
+ const rootDir =
75
+ project.language === 'ts'
76
+ ? project.rootDir.getChild('working')
77
+ : project.rootDir;
78
+
79
+ return dirs
80
+ .map((dir) =>
81
+ exts.map((ext) => rootDir.getChild(dir).getAllFilesGlob(ext)),
82
+ )
83
+ .flat();
84
+ }
85
+ }