@vamship/build-utils 1.0.0-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.
- package/LICENSE +21 -0
- package/README.md +179 -0
- package/package.json +92 -0
- package/src/directory.js +234 -0
- package/src/index.js +22 -0
- package/src/project.js +564 -0
- package/src/task-builders/build/build-js.js +62 -0
- package/src/task-builders/build/build-ts.js +70 -0
- package/src/task-builders/build/build-types.js +47 -0
- package/src/task-builders/build/index.js +52 -0
- package/src/task-builders/clean.js +57 -0
- package/src/task-builders/docs/docs-js.js +41 -0
- package/src/task-builders/docs/docs-ts.js +40 -0
- package/src/task-builders/docs/index.js +32 -0
- package/src/task-builders/format.js +56 -0
- package/src/task-builders/index.js +19 -0
- package/src/task-builders/lint.js +56 -0
- package/src/task-builders/package/index.js +50 -0
- package/src/task-builders/package/package-aws.js +58 -0
- package/src/task-builders/package/package-docker.js +128 -0
- package/src/task-builders/package/package-npm.js +25 -0
- package/src/task-builders/package/package-types.js +54 -0
- package/src/task-builders/package/utils.js +50 -0
- package/src/task-builders/publish/index.js +50 -0
- package/src/task-builders/publish/publish-aws.js +62 -0
- package/src/task-builders/publish/publish-docker.js +78 -0
- package/src/task-builders/publish/publish-npm.js +36 -0
- package/src/task-builders/publish/publish-types.js +36 -0
- package/src/task-builders/test.js +67 -0
package/src/project.js
ADDED
@@ -0,0 +1,564 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const _camelcase = require('camelcase');
|
4
|
+
const Directory = require('./directory');
|
5
|
+
const _dotEnv = require('dotenv');
|
6
|
+
const _dotEnvExpand = require('dotenv-expand');
|
7
|
+
const _fs = require('fs');
|
8
|
+
|
9
|
+
const SUPPORTED_PROJECT_TYPES = [
|
10
|
+
'lib',
|
11
|
+
'cli',
|
12
|
+
'api',
|
13
|
+
'aws-microservice',
|
14
|
+
'container',
|
15
|
+
];
|
16
|
+
const SUPPORTED_LANGUAGES = ['js', 'ts'];
|
17
|
+
|
18
|
+
/**
|
19
|
+
* Represents project configuration. This class will encapsulate information
|
20
|
+
* about projects that should help automate the build/test/deploy toolchain for
|
21
|
+
* a project.
|
22
|
+
*/
|
23
|
+
module.exports = class Project {
|
24
|
+
/**
|
25
|
+
* @param {Object} packageConfig Reference to the project configuration.
|
26
|
+
* This is typically the contents of package.json, with an additional
|
27
|
+
* set of properties called `buildMetadata`.
|
28
|
+
* @param {Object} [buildMetadata] An optional build metadata object that
|
29
|
+
* will override the build metadata defined within packageConfig.
|
30
|
+
*/
|
31
|
+
constructor(packageConfig, buildMetadata) {
|
32
|
+
if (!packageConfig || typeof packageConfig !== 'object') {
|
33
|
+
throw new Error('Invalid packageConfig (arg #1)');
|
34
|
+
}
|
35
|
+
|
36
|
+
const config = Object.assign({}, packageConfig);
|
37
|
+
config.buildMetadata = Object.assign(
|
38
|
+
{},
|
39
|
+
config.buildMetadata,
|
40
|
+
buildMetadata
|
41
|
+
);
|
42
|
+
|
43
|
+
this._name = config.name;
|
44
|
+
this._license = config.license;
|
45
|
+
this._keywords = (config.keywords || []).slice();
|
46
|
+
this._unscopedName = config.name.replace(/^@[^/]*\//, '');
|
47
|
+
this._snakeCasedName = config.name
|
48
|
+
.replace(/^@/, '')
|
49
|
+
.replace(/\//g, '-');
|
50
|
+
this._version = config.version;
|
51
|
+
this._description = config.description;
|
52
|
+
this._initProjectProperties(config.buildMetadata);
|
53
|
+
|
54
|
+
const tree = {
|
55
|
+
src: null,
|
56
|
+
test: {
|
57
|
+
unit: null,
|
58
|
+
api: null,
|
59
|
+
},
|
60
|
+
infra: null,
|
61
|
+
working: {
|
62
|
+
src: null,
|
63
|
+
test: {
|
64
|
+
unit: null,
|
65
|
+
api: null,
|
66
|
+
},
|
67
|
+
infra: null,
|
68
|
+
node_modules: null,
|
69
|
+
},
|
70
|
+
dist: null,
|
71
|
+
docs: null,
|
72
|
+
node_modules: null,
|
73
|
+
coverage: null,
|
74
|
+
'.gulp': null,
|
75
|
+
'.tscache': null,
|
76
|
+
logs: null,
|
77
|
+
'cdk.out': null,
|
78
|
+
};
|
79
|
+
|
80
|
+
if (this._hasExportedTypes) {
|
81
|
+
let rootParentDir = tree;
|
82
|
+
let workingParentDir = tree.working;
|
83
|
+
|
84
|
+
const exportedTypesDirs = this._exportedTypes.split('/');
|
85
|
+
const lastIndex = exportedTypesDirs.length - 1;
|
86
|
+
|
87
|
+
exportedTypesDirs.forEach((dirName, index) => {
|
88
|
+
const isLastIndex = index === lastIndex;
|
89
|
+
|
90
|
+
if (!rootParentDir[dirName]) {
|
91
|
+
rootParentDir[dirName] = isLastIndex ? null : {};
|
92
|
+
}
|
93
|
+
rootParentDir = rootParentDir[dirName];
|
94
|
+
|
95
|
+
if (!workingParentDir[dirName]) {
|
96
|
+
workingParentDir[dirName] = isLastIndex ? null : {};
|
97
|
+
}
|
98
|
+
workingParentDir = workingParentDir[dirName];
|
99
|
+
});
|
100
|
+
}
|
101
|
+
|
102
|
+
this._rootDir = Directory.createTree('./', tree);
|
103
|
+
}
|
104
|
+
|
105
|
+
/**
|
106
|
+
* Initializes project properties using values from a metadata object.
|
107
|
+
*
|
108
|
+
* @private
|
109
|
+
* @param {Object} buildMetadata The metadata to use when initializing
|
110
|
+
* properties.
|
111
|
+
*/
|
112
|
+
_initProjectProperties(buildMetadata) {
|
113
|
+
if (!buildMetadata || typeof buildMetadata !== 'object') {
|
114
|
+
throw new Error('Invalid buildMetadata (arg #1)');
|
115
|
+
}
|
116
|
+
|
117
|
+
const {
|
118
|
+
projectType,
|
119
|
+
language,
|
120
|
+
docker,
|
121
|
+
requiredEnv,
|
122
|
+
exportedTypes,
|
123
|
+
aws,
|
124
|
+
} = buildMetadata;
|
125
|
+
|
126
|
+
if (SUPPORTED_PROJECT_TYPES.indexOf(projectType) < 0) {
|
127
|
+
throw new Error(
|
128
|
+
`Invalid projectType (buildMetadata.projectType).\n\tMust be one of: [${SUPPORTED_PROJECT_TYPES}]`
|
129
|
+
);
|
130
|
+
}
|
131
|
+
|
132
|
+
if (SUPPORTED_LANGUAGES.indexOf(language) < 0) {
|
133
|
+
throw new Error(
|
134
|
+
`Invalid language (buildMetadata.language)\n\tMust be one of: [${SUPPORTED_LANGUAGES}]`
|
135
|
+
);
|
136
|
+
}
|
137
|
+
|
138
|
+
this._requiredEnv = [];
|
139
|
+
if (requiredEnv instanceof Array) {
|
140
|
+
this._requiredEnv = requiredEnv.concat([]);
|
141
|
+
}
|
142
|
+
|
143
|
+
this._projectType = projectType;
|
144
|
+
this._language = language;
|
145
|
+
this._exportedTypes = exportedTypes;
|
146
|
+
|
147
|
+
this._hasTypescript = this._language === 'ts';
|
148
|
+
this._hasServer = this._projectType === 'api';
|
149
|
+
this._hasExportedTypes =
|
150
|
+
typeof exportedTypes === 'string' && exportedTypes.length > 0;
|
151
|
+
|
152
|
+
if (this._projectType === 'aws-microservice') {
|
153
|
+
if (!aws || typeof aws !== 'object') {
|
154
|
+
throw new Error(
|
155
|
+
'The project is an AWS microservice, but does not define AWS configuration'
|
156
|
+
);
|
157
|
+
}
|
158
|
+
|
159
|
+
if (!aws.stacks || typeof aws.stacks !== 'object') {
|
160
|
+
throw new Error(
|
161
|
+
'The project is an AWS microservice, but does not define AWS stacks'
|
162
|
+
);
|
163
|
+
}
|
164
|
+
|
165
|
+
this._awsRegion = aws.region;
|
166
|
+
this._awsProfile = aws.profile;
|
167
|
+
this._cdkStacks = aws.stacks;
|
168
|
+
} else {
|
169
|
+
this._awsRegion = undefined;
|
170
|
+
this._awsProfile = undefined;
|
171
|
+
this._cdkStacks = {};
|
172
|
+
}
|
173
|
+
|
174
|
+
this._hasDocker =
|
175
|
+
this._projectType !== 'lib' &&
|
176
|
+
this._projectType !== 'aws-microservice' &&
|
177
|
+
docker &&
|
178
|
+
typeof docker === 'object';
|
179
|
+
|
180
|
+
this._dockerTargets = this._initDockerTargets(docker);
|
181
|
+
}
|
182
|
+
|
183
|
+
/**
|
184
|
+
* Initialize docker targets for the project.
|
185
|
+
*
|
186
|
+
* @param docker The docker configuration section for the project.
|
187
|
+
*/
|
188
|
+
_initDockerTargets(docker) {
|
189
|
+
if (!this._hasDocker) return [];
|
190
|
+
|
191
|
+
if (docker.repo || docker.registry || docker.buildArgs) {
|
192
|
+
// Deprecated settings
|
193
|
+
let repo = docker.repo;
|
194
|
+
if (!repo) {
|
195
|
+
repo = docker.registry
|
196
|
+
? `${docker.registry}/${this._unscopedName}`
|
197
|
+
: this._unscopedName;
|
198
|
+
}
|
199
|
+
return [
|
200
|
+
{
|
201
|
+
repo,
|
202
|
+
name: 'default',
|
203
|
+
buildFile: 'Dockerfile',
|
204
|
+
buildArgs: this._initializeFromEnv(docker.buildArgs),
|
205
|
+
isDefault: true,
|
206
|
+
isDeprecated: true,
|
207
|
+
},
|
208
|
+
];
|
209
|
+
}
|
210
|
+
|
211
|
+
return Object.keys(docker).map((key) => {
|
212
|
+
const config = docker[key];
|
213
|
+
if (!config || typeof config !== 'object') {
|
214
|
+
throw new Error(
|
215
|
+
`Docker target configuration is invalid for target: [${key}]`
|
216
|
+
);
|
217
|
+
}
|
218
|
+
if (typeof config.repo !== 'string' || config.repo.length <= 0) {
|
219
|
+
throw new Error(
|
220
|
+
`Docker target does not define a valid repo: [${key}]`
|
221
|
+
);
|
222
|
+
}
|
223
|
+
|
224
|
+
const { repo, buildFile, buildArgs } = config;
|
225
|
+
return {
|
226
|
+
repo,
|
227
|
+
name: key,
|
228
|
+
buildFile: buildFile || 'Dockerfile',
|
229
|
+
buildArgs: this._initializeFromEnv(buildArgs),
|
230
|
+
isDefault: key === 'default',
|
231
|
+
isDeprecated: false,
|
232
|
+
};
|
233
|
+
});
|
234
|
+
}
|
235
|
+
|
236
|
+
/**
|
237
|
+
* Loops through the specified object, and replaces specific values from
|
238
|
+
* those defined in the current environment. Returns a new object with the
|
239
|
+
* replaced values. Only properties whose values are '__ENV__' will be
|
240
|
+
* replaced with environment equivalents.
|
241
|
+
*
|
242
|
+
* @param map The initial set of key value mappings.
|
243
|
+
*
|
244
|
+
* @returns {Array} An array of objects containing "name" and "value"
|
245
|
+
* properties that contain the key and the values (replaced from
|
246
|
+
* environment if applicable)
|
247
|
+
*/
|
248
|
+
_initializeFromEnv(map) {
|
249
|
+
if (!map || map instanceof Array || typeof map !== 'object') {
|
250
|
+
return [];
|
251
|
+
}
|
252
|
+
return Object.keys(map).map((name) => {
|
253
|
+
let value = map[name];
|
254
|
+
if (value == '__ENV__') {
|
255
|
+
value = process.env[name];
|
256
|
+
}
|
257
|
+
return { name, value };
|
258
|
+
});
|
259
|
+
}
|
260
|
+
|
261
|
+
/**
|
262
|
+
* Initializes a directory tree for the project based on project properties.
|
263
|
+
*
|
264
|
+
* @private
|
265
|
+
*/
|
266
|
+
_initProjectTree() {
|
267
|
+
const tree = {
|
268
|
+
src: null,
|
269
|
+
test: {
|
270
|
+
unit: null,
|
271
|
+
api: null,
|
272
|
+
},
|
273
|
+
infra: null,
|
274
|
+
working: {
|
275
|
+
src: null,
|
276
|
+
test: {
|
277
|
+
unit: null,
|
278
|
+
api: null,
|
279
|
+
},
|
280
|
+
infra: null,
|
281
|
+
node_modules: null,
|
282
|
+
},
|
283
|
+
dist: null,
|
284
|
+
docs: null,
|
285
|
+
node_modules: null,
|
286
|
+
coverage: null,
|
287
|
+
'.gulp': null,
|
288
|
+
'.tscache': null,
|
289
|
+
logs: null,
|
290
|
+
'cdk.out': null,
|
291
|
+
};
|
292
|
+
|
293
|
+
if (this._projectType === 'aws-microservice') {
|
294
|
+
tree.infra = null;
|
295
|
+
tree.working.infra = null;
|
296
|
+
tree.working.node_modules = null;
|
297
|
+
tree['cdk.out'] = null;
|
298
|
+
}
|
299
|
+
}
|
300
|
+
|
301
|
+
/**
|
302
|
+
* An object representation of the project's root directory.
|
303
|
+
*
|
304
|
+
* @returns {Directory}
|
305
|
+
*/
|
306
|
+
get rootDir() {
|
307
|
+
return this._rootDir;
|
308
|
+
}
|
309
|
+
|
310
|
+
/**
|
311
|
+
* An object representation of the root directory for all javascript files.
|
312
|
+
* For typescript projects, this would be the directory containing the
|
313
|
+
* transpiled files.
|
314
|
+
*
|
315
|
+
* @returns {Directory}
|
316
|
+
*/
|
317
|
+
get jsRootDir() {
|
318
|
+
return this._hasTypescript
|
319
|
+
? this._rootDir.getChild('working')
|
320
|
+
: this._rootDir;
|
321
|
+
}
|
322
|
+
|
323
|
+
/**
|
324
|
+
* The name of the project as defined in package.json.
|
325
|
+
*
|
326
|
+
* @return {String}
|
327
|
+
*/
|
328
|
+
get name() {
|
329
|
+
return this._name;
|
330
|
+
}
|
331
|
+
|
332
|
+
/**
|
333
|
+
* The license of the project as defined in package.json.
|
334
|
+
*
|
335
|
+
* @return {String}
|
336
|
+
*/
|
337
|
+
get license() {
|
338
|
+
return this._license;
|
339
|
+
}
|
340
|
+
|
341
|
+
/**
|
342
|
+
* The keywords for the project as defined in package.json.
|
343
|
+
*
|
344
|
+
* @return {String}
|
345
|
+
*/
|
346
|
+
get keywords() {
|
347
|
+
return this._keywords;
|
348
|
+
}
|
349
|
+
|
350
|
+
/**
|
351
|
+
* The name of the project without including its scope. IF the project has
|
352
|
+
* no scope, the unscoped name will match the project name.
|
353
|
+
*
|
354
|
+
* @return {String}
|
355
|
+
*/
|
356
|
+
get unscopedName() {
|
357
|
+
return this._unscopedName;
|
358
|
+
}
|
359
|
+
|
360
|
+
/**
|
361
|
+
* The name of the project formatted in snake case. Ideal for use when
|
362
|
+
* generating package names. This property does not include the file
|
363
|
+
* extension (.tgz).
|
364
|
+
*/
|
365
|
+
get snakeCasedName() {
|
366
|
+
return this._snakeCasedName;
|
367
|
+
}
|
368
|
+
|
369
|
+
/**
|
370
|
+
* The version of the project as defined in package.json.
|
371
|
+
*
|
372
|
+
* @return {String}
|
373
|
+
*/
|
374
|
+
get version() {
|
375
|
+
return this._version;
|
376
|
+
}
|
377
|
+
|
378
|
+
/**
|
379
|
+
* The description of the project as defined in package.json.
|
380
|
+
*
|
381
|
+
* @return {String}
|
382
|
+
*/
|
383
|
+
get description() {
|
384
|
+
return this._description;
|
385
|
+
}
|
386
|
+
|
387
|
+
/**
|
388
|
+
* Gets the name of the expected configuration file name based on the name
|
389
|
+
* of the project.
|
390
|
+
*/
|
391
|
+
get configFileName() {
|
392
|
+
return `.${_camelcase(this._unscopedName)}rc`;
|
393
|
+
}
|
394
|
+
|
395
|
+
/**
|
396
|
+
* The project type of the project (lib/api/cli).
|
397
|
+
*
|
398
|
+
* @return {String}
|
399
|
+
*/
|
400
|
+
get projectType() {
|
401
|
+
return this._projectType;
|
402
|
+
}
|
403
|
+
|
404
|
+
/**
|
405
|
+
* The language used by the project (js/ts).
|
406
|
+
*
|
407
|
+
* @return {String}
|
408
|
+
*/
|
409
|
+
get language() {
|
410
|
+
return this._language;
|
411
|
+
}
|
412
|
+
|
413
|
+
/**
|
414
|
+
* Returns the AWS region configured for the project.
|
415
|
+
*
|
416
|
+
* @return {String}
|
417
|
+
*/
|
418
|
+
get awsRegion() {
|
419
|
+
return this._awsRegion;
|
420
|
+
}
|
421
|
+
|
422
|
+
/**
|
423
|
+
* Returns the AWS profile configured for the project.
|
424
|
+
*
|
425
|
+
* @return {String}
|
426
|
+
*/
|
427
|
+
get awsProfile() {
|
428
|
+
return this._awsProfile;
|
429
|
+
}
|
430
|
+
|
431
|
+
/**
|
432
|
+
* The path to the directory that contains the types exported by this
|
433
|
+
* project.
|
434
|
+
*
|
435
|
+
* @return {String}
|
436
|
+
*/
|
437
|
+
get exportedTypes() {
|
438
|
+
return this._exportedTypes;
|
439
|
+
}
|
440
|
+
|
441
|
+
/**
|
442
|
+
* Determines whether or not the project can be packaged up as a docker
|
443
|
+
* image.
|
444
|
+
*
|
445
|
+
* @return {Boolean}
|
446
|
+
*/
|
447
|
+
get hasDocker() {
|
448
|
+
return this._hasDocker;
|
449
|
+
}
|
450
|
+
|
451
|
+
/**
|
452
|
+
* Determines whether or not the project contains typescript files.
|
453
|
+
*
|
454
|
+
* @return {Boolean}
|
455
|
+
*/
|
456
|
+
get hasTypescript() {
|
457
|
+
return this._hasTypescript;
|
458
|
+
}
|
459
|
+
|
460
|
+
/**
|
461
|
+
* Determines whether or not the project has a server component that might
|
462
|
+
* require API tests or the ability to host a local server.
|
463
|
+
*
|
464
|
+
* @return {Boolean}
|
465
|
+
*/
|
466
|
+
get hasServer() {
|
467
|
+
return this._hasServer;
|
468
|
+
}
|
469
|
+
|
470
|
+
/**
|
471
|
+
* Determines if the project has any types to export.
|
472
|
+
*
|
473
|
+
* @return {String}
|
474
|
+
*/
|
475
|
+
get hasExportedTypes() {
|
476
|
+
return this._hasExportedTypes;
|
477
|
+
}
|
478
|
+
|
479
|
+
/**
|
480
|
+
* Initializes a list of environment variables from the specified files.
|
481
|
+
* If environment variables are repeated in files, the declaration in the
|
482
|
+
* first file takes precedence over the others.
|
483
|
+
*
|
484
|
+
* @param {Array} [files=[]] A list of files to load environment variables
|
485
|
+
* from.
|
486
|
+
*/
|
487
|
+
initEnv(envFiles) {
|
488
|
+
if (!(envFiles instanceof Array)) {
|
489
|
+
envFiles = [];
|
490
|
+
}
|
491
|
+
envFiles
|
492
|
+
.filter((file) => _fs.existsSync(file))
|
493
|
+
.forEach((file) => _dotEnvExpand(_dotEnv.config({ path: file })));
|
494
|
+
}
|
495
|
+
|
496
|
+
/**
|
497
|
+
* Returns a list of required environment variables. These parameters can
|
498
|
+
* be checked during build/package time to ensure that they exist, before
|
499
|
+
* performing any actions.
|
500
|
+
*
|
501
|
+
* @return {Array}
|
502
|
+
*/
|
503
|
+
getRequiredEnv() {
|
504
|
+
return this._requiredEnv.concat([]);
|
505
|
+
}
|
506
|
+
|
507
|
+
/**
|
508
|
+
* Checks to see if all required variables have been defined in the
|
509
|
+
* environment. This is typically a runtime call, executed prior to
|
510
|
+
* building/packaging a project.
|
511
|
+
*/
|
512
|
+
validateRequiredEnv() {
|
513
|
+
const missingVars = [];
|
514
|
+
this._requiredEnv.forEach((param) => {
|
515
|
+
if (!process.env[param]) {
|
516
|
+
missingVars.push(param);
|
517
|
+
}
|
518
|
+
});
|
519
|
+
if (missingVars.length > 0) {
|
520
|
+
throw new Error(
|
521
|
+
`Required environment variables not defined: ${missingVars}`
|
522
|
+
);
|
523
|
+
}
|
524
|
+
}
|
525
|
+
|
526
|
+
/**
|
527
|
+
* Returns a list of docker targets defined for the project. Every target
|
528
|
+
* will define the following properties:
|
529
|
+
* - repo: The docker repo
|
530
|
+
* - buildFile: The name of the build file to use
|
531
|
+
* - buildArgs: Arguments to be passed to the docker build
|
532
|
+
* - isDefault: Determines if the current target is the default one
|
533
|
+
* - isDeprecated: Determines if the target uses a deprecated configuration.
|
534
|
+
*
|
535
|
+
* @return {Array}
|
536
|
+
*/
|
537
|
+
getDockerTargets() {
|
538
|
+
return this._dockerTargets.concat([]);
|
539
|
+
}
|
540
|
+
|
541
|
+
/**
|
542
|
+
* Returns a list of CDK stack keys defined for the project. These stack
|
543
|
+
* keys will be used to generate deploy tasks for each. Each key maps to a
|
544
|
+
* specific CDK stack that can be deployed.
|
545
|
+
*
|
546
|
+
* @return {Array} A list of stack keys
|
547
|
+
*/
|
548
|
+
getCdkStacks() {
|
549
|
+
return Object.keys(this._cdkStacks);
|
550
|
+
}
|
551
|
+
|
552
|
+
/**
|
553
|
+
* Returns the name of the stack corresponding to the stack key.
|
554
|
+
*
|
555
|
+
* @param {String} key The CDK stack key to use when looking up the name.
|
556
|
+
* @return {String} The stack name that maps to the key.
|
557
|
+
*/
|
558
|
+
getCdkStackName(key) {
|
559
|
+
if (typeof key !== 'string' || key.length <= 0) {
|
560
|
+
throw new Error('Invalid stack key (arg #1)');
|
561
|
+
}
|
562
|
+
return this._cdkStacks[key];
|
563
|
+
}
|
564
|
+
};
|
@@ -0,0 +1,62 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const _gulp = require('gulp');
|
4
|
+
|
5
|
+
/**
|
6
|
+
* Sub builder that creates a task that will copy javascript files from source
|
7
|
+
* to build directories. This method will return a watcher if the watch option
|
8
|
+
* 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 dirs = ['src', 'test'];
|
24
|
+
if (project.projectType === 'aws-microservice') {
|
25
|
+
dirs.push('infra');
|
26
|
+
}
|
27
|
+
|
28
|
+
const extras = [
|
29
|
+
project.configFileName,
|
30
|
+
'package.json',
|
31
|
+
'.npmignore',
|
32
|
+
'.npmrc',
|
33
|
+
];
|
34
|
+
|
35
|
+
if (project.hasDocker) {
|
36
|
+
extras.push('Dockerfile*');
|
37
|
+
}
|
38
|
+
|
39
|
+
const paths = dirs
|
40
|
+
.map((dir) => rootDir.getChild(dir))
|
41
|
+
.map((dir) => ['js', 'json'].map((ext) => dir.getAllFilesGlob(ext)))
|
42
|
+
.reduce((result, arr) => result.concat(arr), [])
|
43
|
+
.concat(extras.map((item) => rootDir.getFileGlob(item)));
|
44
|
+
|
45
|
+
const task = () =>
|
46
|
+
_gulp
|
47
|
+
.src(paths, { allowEmpty: true, base: rootDir.globPath })
|
48
|
+
.pipe(_gulp.dest(workingDir.absolutePath));
|
49
|
+
|
50
|
+
task.displayName = 'build-js';
|
51
|
+
task.description = 'Copy javascript files from source to build directory';
|
52
|
+
|
53
|
+
if (watch) {
|
54
|
+
const watchTask = () => _gulp.watch(paths, task);
|
55
|
+
watchTask.displayName = 'watch-build-js';
|
56
|
+
watchTask.description =
|
57
|
+
'Automatically copy javascript files to build directory on change';
|
58
|
+
|
59
|
+
return watchTask;
|
60
|
+
}
|
61
|
+
return task;
|
62
|
+
};
|
@@ -0,0 +1,70 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const _gulp = require('gulp');
|
4
|
+
const _typescript = require('gulp-typescript');
|
5
|
+
|
6
|
+
/**
|
7
|
+
* Sub builder that creates a task that will transpile typescript files into
|
8
|
+
* javascript files. This method will return a watcher if the watch option
|
9
|
+
* is set to true.
|
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 { watch } = Object.assign({ watch: false }, options);
|
21
|
+
const rootDir = project.rootDir;
|
22
|
+
const workingDir = rootDir.getChild('working');
|
23
|
+
|
24
|
+
const dirs = ['src', 'test'];
|
25
|
+
if (project.projectType === 'aws-microservice') {
|
26
|
+
dirs.push('infra');
|
27
|
+
}
|
28
|
+
|
29
|
+
const tsProject = _typescript.createProject('tsconfig.json');
|
30
|
+
|
31
|
+
const paths = dirs
|
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 distFiles = [
|
37
|
+
rootDir.getFileGlob('package-lock.json'),
|
38
|
+
rootDir.getFileGlob('Dockerfile*'),
|
39
|
+
rootDir.getFileGlob('LICENSE'),
|
40
|
+
rootDir.getFileGlob('README.md'),
|
41
|
+
rootDir.getFileGlob('.env'),
|
42
|
+
rootDir.getFileGlob(project.configFileName),
|
43
|
+
];
|
44
|
+
|
45
|
+
const buildTask = () =>
|
46
|
+
_gulp
|
47
|
+
.src(paths, { base: rootDir.globPath })
|
48
|
+
.pipe(tsProject())
|
49
|
+
.pipe(_gulp.dest(workingDir.absolutePath));
|
50
|
+
|
51
|
+
const copyTask = () =>
|
52
|
+
_gulp
|
53
|
+
.src(distFiles, { allowEmpty: true })
|
54
|
+
.pipe(_gulp.dest(workingDir.absolutePath));
|
55
|
+
|
56
|
+
const task = _gulp.parallel([copyTask, buildTask]);
|
57
|
+
|
58
|
+
task.displayName = 'build-ts';
|
59
|
+
task.description = 'Build typescript source files to javascript files';
|
60
|
+
|
61
|
+
if (watch) {
|
62
|
+
const watchTask = () => _gulp.watch(paths, task);
|
63
|
+
watchTask.displayName = 'watch-build-ts';
|
64
|
+
watchTask.description =
|
65
|
+
'Automatically build typescript files on change';
|
66
|
+
|
67
|
+
return watchTask;
|
68
|
+
}
|
69
|
+
return task;
|
70
|
+
};
|