• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

serverless-heaven / serverless-webpack / 12980696548

27 Jan 2025 02:04AM UTC coverage: 92.492%. First build
12980696548

Pull #2028

github

web-flow
Merge 9515262c3 into 9a2ffbf16
Pull Request #2028: build(deps): bump dependabot/fetch-metadata from 2.2.0 to 2.3.0

984 of 1104 branches covered (89.13%)

Branch coverage included in aggregate %.

2576 of 2745 relevant lines covered (93.84%)

70.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.21
/lib/packExternalModules.js
1
'use strict';
2✔
2

2✔
3
const BbPromise = require('bluebird');
2✔
4
const _ = require('lodash');
2✔
5
const path = require('path');
2✔
6
const fse = require('fs-extra');
2✔
7
const findWorkspaceRoot = require('find-yarn-workspace-root');
2✔
8

2✔
9
const Packagers = require('./packagers');
2✔
10
const { isProviderGoogle } = require('./utils');
2✔
11

2✔
12
function rebaseFileReferences(pathToPackageRoot, moduleVersion) {
270✔
13
  if (/^(?:file:[^/]{2}|\.\/|\.\.\/)/.test(moduleVersion)) {
270✔
14
    const filePath = _.replace(moduleVersion, /^file:/, '');
4✔
15
    return _.replace(
4✔
16
      `${_.startsWith(moduleVersion, 'file:') ? 'file:' : ''}${pathToPackageRoot}/${filePath}`,
4!
17
      /\\/g,
4✔
18
      '/'
4✔
19
    );
4✔
20
  }
4✔
21

266✔
22
  return moduleVersion;
266✔
23
}
266✔
24

2✔
25
/**
2✔
26
 * Add the given modules to a package json's dependencies.
2✔
27
 */
2✔
28
function addModulesToPackageJson(externalModules, packageJson, pathToPackageRoot) {
90✔
29
  _.forEach(externalModules.sort(), externalModule => {
90✔
30
    const splitModule = _.split(externalModule, '@');
270✔
31
    // If we have a scoped module we have to re-add the @
270✔
32
    if (_.startsWith(externalModule, '@')) {
270✔
33
      splitModule.splice(0, 1);
62✔
34
      splitModule[0] = '@' + splitModule[0];
62✔
35
    }
62✔
36
    let moduleVersion = _.join(_.tail(splitModule), '@');
270✔
37
    // We have to rebase file references to the target package.json
270✔
38
    moduleVersion = rebaseFileReferences(pathToPackageRoot, moduleVersion);
270✔
39
    packageJson.dependencies = packageJson.dependencies || {};
270✔
40
    packageJson.dependencies[_.first(splitModule)] = moduleVersion;
270✔
41
  });
90✔
42
}
90✔
43

2✔
44
/**
2✔
45
 * Remove a given list of excluded modules from a module list
2✔
46
 * @this - The active plugin instance
2✔
47
 */
2✔
48
function removeExcludedModules(modules, packageForceExcludes, log) {
92✔
49
  // eslint-disable-next-line lodash/prefer-immutable-method
92✔
50
  const excludedModules = _.remove(modules, externalModule => {
92✔
51
    const splitModule = _.split(externalModule, '@');
274✔
52
    // If we have a scoped module we have to re-add the @
274✔
53
    if (_.startsWith(externalModule, '@')) {
274✔
54
      splitModule.splice(0, 1);
62✔
55
      splitModule[0] = '@' + splitModule[0];
62✔
56
    }
62✔
57
    const moduleName = _.first(splitModule);
274✔
58
    return _.includes(packageForceExcludes, moduleName);
274✔
59
  });
92✔
60

92✔
61
  if (log && !_.isEmpty(excludedModules)) {
92✔
62
    if (this.log) {
2!
63
      this.log(`Excluding external modules: ${_.join(excludedModules, ', ')}`);
×
64
    } else {
2✔
65
      this.serverless.cli.log(`Excluding external modules: ${_.join(excludedModules, ', ')}`);
2✔
66
    }
2✔
67
  }
2✔
68
}
92✔
69

2✔
70
/**
2✔
71
 * Resolve the needed versions of production dependencies for external modules.
2✔
72
 * @this - The active plugin instance
2✔
73
 */
2✔
74
function getProdModules(externalModules, packagePath, nodeModulesRelativeDir, dependencyGraph, forceExcludes) {
106✔
75
  const packageJsonPath = path.join(process.cwd(), packagePath);
106✔
76
  const packageJson = require(packageJsonPath);
106✔
77
  const prodModules = [];
106✔
78

106✔
79
  // only process the module stated in dependencies section
106✔
80
  if (!packageJson.dependencies) {
106!
81
    return [];
×
82
  }
×
83

106✔
84
  // Get versions of all transient modules
106✔
85
  _.forEach(externalModules, module => {
106✔
86
    let moduleVersion = packageJson.dependencies[module.external];
288✔
87

288✔
88
    if (moduleVersion) {
288✔
89
      prodModules.push(`${module.external}@${moduleVersion}`);
258✔
90

258✔
91
      let nodeModulesBase = path.join(path.dirname(path.join(process.cwd(), packagePath)), 'node_modules');
258✔
92

258✔
93
      if (nodeModulesRelativeDir) {
258✔
94
        const customNodeModulesDir = path.join(process.cwd(), nodeModulesRelativeDir, 'node_modules');
12✔
95

12✔
96
        if (fse.pathExistsSync(customNodeModulesDir)) {
12✔
97
          nodeModulesBase = customNodeModulesDir;
12✔
98
        } else {
12!
99
          if (this.log) {
×
100
            this.log.warning(`${customNodeModulesDir} dose not exist. Please check nodeModulesRelativeDir setting`);
×
101
          } else {
×
102
            this.serverless.cli.log(
×
103
              `WARNING: ${customNodeModulesDir} dose not exist. Please check nodeModulesRelativeDir setting`
×
104
            );
×
105
          }
×
106
        }
×
107
      }
12✔
108

258✔
109
      // Check if the module has any peer dependencies and include them too
258✔
110
      try {
258✔
111
        const modulePackagePath = path.join(nodeModulesBase, module.external, 'package.json');
258✔
112

258✔
113
        const peerDependencies = require(modulePackagePath).peerDependencies;
258✔
114
        if (!_.isEmpty(peerDependencies)) {
258✔
115
          if (this.log) {
12!
116
            this.log.verbose(`Adding explicit peers for dependency ${module.external}`);
×
117
          } else {
12✔
118
            this.options.verbose && this.serverless.cli.log(`Adding explicit peers for dependency ${module.external}`);
12✔
119
          }
12✔
120

12✔
121
          const peerDependenciesMeta = require(modulePackagePath).peerDependenciesMeta;
12✔
122

12✔
123
          if (!_.isEmpty(peerDependenciesMeta)) {
12✔
124
            _.forEach(peerDependencies, (value, key) => {
8✔
125
              if (peerDependenciesMeta[key] && peerDependenciesMeta[key].optional === true) {
12✔
126
                if (this.log) {
4!
127
                  this.log.verbose(
×
128
                    `Skipping peers dependency ${key} for dependency ${module.external} because it's optional`
×
129
                  );
×
130
                } else {
4✔
131
                  this.options.verbose &&
4✔
132
                    this.serverless.cli.log(
4✔
133
                      `Skipping peers dependency ${key} for dependency ${module.external} because it's optional`
4✔
134
                    );
4✔
135
                }
4✔
136
                _.unset(peerDependencies, key);
4✔
137
              }
4✔
138
            });
8✔
139
          }
8✔
140

12✔
141
          if (!_.isEmpty(peerDependencies)) {
12✔
142
            const peerModules = getProdModules.call(
12✔
143
              this,
12✔
144
              _.map(peerDependencies, (value, key) => ({ external: key })),
12✔
145
              packagePath,
12✔
146
              nodeModulesRelativeDir,
12✔
147
              dependencyGraph,
12✔
148
              forceExcludes
12✔
149
            );
12✔
150
            Array.prototype.push.apply(prodModules, peerModules);
12✔
151
          }
12✔
152
        }
12✔
153
      } catch (e) {
258✔
154
        if (this.log) {
110✔
155
          this.log.warning(
4✔
156
            `Could not check for peer dependencies of ${module.external}. Set nodeModulesRelativeDir if node_modules is in different directory.`
4✔
157
          );
4✔
158
        } else {
110✔
159
          this.serverless.cli.log(
106✔
160
            `WARNING: Could not check for peer dependencies of ${module.external}. Set nodeModulesRelativeDir if node_modules is in different directory.`
106✔
161
          );
106✔
162
        }
106✔
163
      }
110✔
164
    } else {
288✔
165
      if (!packageJson.devDependencies || !packageJson.devDependencies[module.external]) {
30✔
166
        // Add transient dependencies if they appear not in the service's dev dependencies
16✔
167
        const originInfo = _.get(dependencyGraph, 'dependencies', {})[module.origin] || {};
16✔
168
        moduleVersion = _.get(_.get(originInfo, 'dependencies', {})[module.external], 'version');
16✔
169
        if (!moduleVersion) {
16✔
170
          // eslint-disable-next-line lodash/path-style
16✔
171
          moduleVersion = _.get(dependencyGraph, ['dependencies', module.external, 'version']);
16✔
172
        }
16✔
173
        if (!moduleVersion) {
16✔
174
          if (this.log) {
12!
175
            this.log.warning(`Could not determine version of module ${module.external}`);
×
176
          } else {
12✔
177
            this.serverless.cli.log(`WARNING: Could not determine version of module ${module.external}`);
12✔
178
          }
12✔
179
        }
12✔
180
        prodModules.push(moduleVersion ? `${module.external}@${moduleVersion}` : module.external);
16✔
181
      } else if (
30✔
182
        packageJson.devDependencies &&
14✔
183
        packageJson.devDependencies[module.external] &&
14✔
184
        !_.includes(forceExcludes, module.external)
14✔
185
      ) {
14✔
186
        // To minimize the chance of breaking setups we whitelist packages available on AWS here. These are due to the previously missing check
10✔
187
        // most likely set in devDependencies and should not lead to an error now.
10✔
188
        const ignoredDevDependencies = ['aws-sdk'];
10✔
189

10✔
190
        if (!_.includes(ignoredDevDependencies, module.external)) {
10✔
191
          // Runtime dependency found in devDependencies but not forcefully excluded
2✔
192
          if (this.log) {
2!
193
            this.log.error(
×
194
              `Runtime dependency '${module.external}' found in devDependencies. Move it to dependencies or use forceExclude to explicitly exclude it.`
×
195
            );
×
196
          } else {
2✔
197
            this.serverless.cli.log(
2✔
198
              `ERROR: Runtime dependency '${module.external}' found in devDependencies. Move it to dependencies or use forceExclude to explicitly exclude it.`
2✔
199
            );
2✔
200
          }
2✔
201
          throw new this.serverless.classes.Error(`Serverless-webpack dependency error: ${module.external}.`);
2✔
202
        }
2✔
203
        if (this.log) {
10✔
204
          this.log.verbose(
4✔
205
            `Runtime dependency '${module.external}' found in devDependencies. It has been excluded automatically.`
4✔
206
          );
4✔
207
        } else {
4✔
208
          this.options.verbose &&
4✔
209
            this.serverless.cli.log(
4✔
210
              `INFO: Runtime dependency '${module.external}' found in devDependencies. It has been excluded automatically.`
4✔
211
            );
4✔
212
        }
4✔
213
      }
10✔
214
    }
30✔
215
  });
106✔
216

106✔
217
  return prodModules;
106✔
218
}
106✔
219

2✔
220
module.exports = {
2✔
221
  /**
2✔
222
   * We need a performant algorithm to install the packages for each single
2✔
223
   * function (in case we package individually).
2✔
224
   * (1) We fetch ALL packages needed by ALL functions in a first step
2✔
225
   * and use this as a base npm checkout. The checkout will be done to a
2✔
226
   * separate temporary directory with a package.json that contains everything.
2✔
227
   * (2) For each single compile we copy the whole node_modules to the compile
2✔
228
   * directory and create a (function) compile specific package.json and store
2✔
229
   * it in the compile directory. Now we start npm again there, and npm will just
2✔
230
   * remove the superfluous packages and optimize the remaining dependencies.
2✔
231
   * This will utilize the npm cache at its best and give us the needed results
2✔
232
   * and performance.
2✔
233
   */
2✔
234
  packExternalModules() {
2✔
235
    if (this.skipCompile) {
56✔
236
      return BbPromise.resolve();
2✔
237
    }
2✔
238

54✔
239
    const stats = this.compileStats;
54✔
240

54✔
241
    const includes = this.configuration.includeModules;
54✔
242

54✔
243
    if (!includes) {
56✔
244
      return BbPromise.resolve();
2✔
245
    }
2✔
246
    if (this.log) {
56✔
247
      this.log.verbose('Packing external modules');
6✔
248
      this.progress.get('webpack').notice('[Webpack] Packing external modules');
6✔
249
    }
6✔
250

52✔
251
    // Read plugin configuration
52✔
252
    const packageForceIncludes = _.get(includes, 'forceInclude', []);
52✔
253
    const packageForceExcludes = _.get(includes, 'forceExclude', []);
52✔
254
    const packagePath = includes.packagePath || './package.json';
56✔
255
    const nodeModulesRelativeDir = includes.nodeModulesRelativeDir;
56✔
256
    const packageJsonPath = path.join(process.cwd(), packagePath);
56✔
257
    const packageScripts = _.reduce(
56✔
258
      this.configuration.packagerOptions.scripts || [],
56✔
259
      (__, script, index) => {
56✔
260
        __[`script${index}`] = script;
×
261
        return __;
×
262
      },
56✔
263
      {}
56✔
264
    );
56✔
265

56✔
266
    // Determine and create packager
56✔
267
    return BbPromise.try(() => Packagers.get.call(this, this.configuration.packager)).then(packager => {
56✔
268
      // Fetch needed original package.json sections
52✔
269
      const sectionNames = packager.copyPackageSectionNames(this.configuration.packagerOptions);
52✔
270
      const packageJson = this.serverless.utils.readFileSync(packageJsonPath);
52✔
271
      const packageSections = _.pick(packageJson, sectionNames);
52✔
272
      if (!_.isEmpty(packageSections)) {
52✔
273
        if (this.log) {
4!
274
          this.log.verbose(`Using package.json sections ${_.join(_.keys(packageSections), ', ')}`);
×
275
        } else {
4✔
276
          this.options.verbose &&
4✔
277
            this.serverless.cli.log(`Using package.json sections ${_.join(_.keys(packageSections), ', ')}`);
4✔
278
        }
4✔
279
      }
4✔
280

52✔
281
      // Get first level dependency graph
52✔
282
      if (this.log) {
52✔
283
        this.log.verbose(`Fetch dependency graph from ${packageJsonPath}`);
6✔
284
      } else {
52✔
285
        this.options.verbose && this.serverless.cli.log(`Fetch dependency graph from ${packageJsonPath}`);
46✔
286
      }
46✔
287

52✔
288
      return packager
52✔
289
        .getProdDependencies(path.dirname(packageJsonPath), 1, this.configuration.packagerOptions)
52✔
290
        .then(dependencyGraph => {
52✔
291
          const problems = _.get(dependencyGraph, 'problems', []);
50✔
292
          if (this.options.verbose && !_.isEmpty(problems)) {
50✔
293
            if (this.log) {
2!
294
              this.log.verbose(`Ignoring ${_.size(problems)} NPM errors:`);
×
295
            } else {
2✔
296
              this.serverless.cli.log(`Ignoring ${_.size(problems)} NPM errors:`);
2✔
297
            }
2✔
298
            _.forEach(problems, problem => {
2✔
299
              if (this.log) {
4!
300
                this.log.verbose(`=> ${problem}`);
×
301
              } else {
4✔
302
                this.serverless.cli.log(`=> ${problem}`);
4✔
303
              }
4✔
304
            });
2✔
305
          }
2✔
306

50✔
307
          // (1) Generate dependency composition
50✔
308
          const compositeModules = _.uniq(
50✔
309
            _.flatMap(stats.stats, compileStats => {
50✔
310
              const externalModules = _.concat(
50✔
311
                compileStats.externalModules,
50✔
312
                _.map(packageForceIncludes, whitelistedPackage => ({
50✔
313
                  external: whitelistedPackage
8✔
314
                }))
50✔
315
              );
50✔
316
              return getProdModules.call(
50✔
317
                this,
50✔
318
                externalModules,
50✔
319
                packagePath,
50✔
320
                nodeModulesRelativeDir,
50✔
321
                dependencyGraph,
50✔
322
                packageForceExcludes
50✔
323
              );
50✔
324
            })
50✔
325
          );
50✔
326
          removeExcludedModules.call(this, compositeModules, packageForceExcludes, true);
50✔
327

50✔
328
          if (_.isEmpty(compositeModules)) {
50✔
329
            // The compiled code does not reference any external modules at all
2✔
330
            if (this.log) {
2!
331
              this.log('No external modules needed');
×
332
            } else {
2✔
333
              this.serverless.cli.log('No external modules needed');
2✔
334
            }
2✔
335
            return BbPromise.resolve();
2✔
336
          }
2✔
337

46✔
338
          // (1.a) Install all needed modules
46✔
339
          const compositeModulePath = path.join(this.webpackOutputPath, 'dependencies');
46✔
340
          const compositePackageJson = path.join(compositeModulePath, 'package.json');
46✔
341

46✔
342
          // (1.a.1) Create a package.json
46✔
343
          const compositePackage = _.defaults(
46✔
344
            {
46✔
345
              name: this.serverless.service.service,
46✔
346
              version: '1.0.0',
46✔
347
              description: `Packaged externals for ${this.serverless.service.service}`,
46✔
348
              private: true,
46✔
349
              scripts: packageScripts
46✔
350
            },
46✔
351
            packageSections
46✔
352
          );
46✔
353
          const relPath = path.relative(compositeModulePath, path.dirname(packageJsonPath));
46✔
354
          addModulesToPackageJson(compositeModules, compositePackage, relPath);
46✔
355
          this.serverless.utils.writeFileSync(compositePackageJson, JSON.stringify(compositePackage, null, 2));
46✔
356

46✔
357
          // (1.a.2) Copy package-lock.json if it exists, to prevent unwanted upgrades
46✔
358
          const packagerOptions = this.configuration.packagerOptions || {};
50!
359
          const packageLockPath = path.join(
50✔
360
            findWorkspaceRoot(path.dirname(packageJsonPath)) || path.dirname(packageJsonPath),
50✔
361
            packagerOptions.lockFile || packager.lockfileName
50✔
362
          );
50✔
363
          let hasPackageLock = false;
50✔
364
          return BbPromise.fromCallback(cb => fse.pathExists(packageLockPath, cb))
50✔
365
            .then(exists => {
50✔
366
              if (exists) {
46✔
367
                if (this.log) {
16✔
368
                  this.log('Package lock found - Using locked versions');
6✔
369
                } else {
16✔
370
                  this.serverless.cli.log('Package lock found - Using locked versions');
10✔
371
                }
10✔
372
                try {
16✔
373
                  let packageLockFile = this.serverless.utils.readFileSync(packageLockPath);
16✔
374
                  packageLockFile = packager.rebaseLockfile(relPath, packageLockFile);
16✔
375
                  if (_.isObject(packageLockFile)) {
16✔
376
                    packageLockFile = JSON.stringify(packageLockFile, null, 2);
8✔
377
                  }
8✔
378

12✔
379
                  this.serverless.utils.writeFileSync(
12✔
380
                    path.join(compositeModulePath, packager.lockfileName),
12✔
381
                    packageLockFile
12✔
382
                  );
12✔
383
                  hasPackageLock = true;
12✔
384
                } catch (err) {
16✔
385
                  if (this.log) {
4!
386
                    this.log.warning(`Could not read lock file: ${err.message}`);
×
387
                  } else {
4✔
388
                    this.serverless.cli.log(`Warning: Could not read lock file: ${err.message}`);
4✔
389
                  }
4✔
390
                }
4✔
391
              }
16✔
392
              return BbPromise.resolve();
46✔
393
            })
50✔
394
            .then(() => {
50✔
395
              const start = _.now();
46✔
396
              if (this.log) {
46✔
397
                this.log('Packing external modules: ' + compositeModules.join(', '));
6✔
398
              } else {
46✔
399
                this.serverless.cli.log('Packing external modules: ' + compositeModules.join(', '));
40✔
400
              }
40✔
401

46✔
402
              return packager.getPackagerVersion(compositeModulePath).then(version => {
46✔
403
                return packager
46✔
404
                  .install(compositeModulePath, this.configuration.packagerOptions, version)
46✔
405
                  .then(() => {
46✔
406
                    if (this.log) {
44✔
407
                      this.log.verbose(`Package took [${_.now() - start} ms]`);
6✔
408
                    } else {
44✔
409
                      this.options.verbose && this.serverless.cli.log(`Package took [${_.now() - start} ms]`);
38✔
410
                    }
38✔
411
                    return null;
44✔
412
                  })
46✔
413
                  .return(stats.stats);
46✔
414
              });
46✔
415
            })
50✔
416
            .mapSeries(compileStats => {
50✔
417
              const modulePath = compileStats.outputPath;
44✔
418

44✔
419
              // Create package.json
44✔
420
              const modulePackageJson = path.join(modulePath, 'package.json');
44✔
421
              const modulePackage = _.defaults(
44✔
422
                {
44✔
423
                  name: this.serverless.service.service,
44✔
424
                  version: '1.0.0',
44✔
425
                  description: `Packaged externals for ${this.serverless.service.service}`,
44✔
426
                  private: true,
44✔
427
                  scripts: packageScripts,
44✔
428
                  dependencies: {}
44✔
429
                },
44✔
430
                packageSections
44✔
431
              );
44✔
432
              const prodModules = getProdModules.call(
44✔
433
                this,
44✔
434
                _.concat(
44✔
435
                  compileStats.externalModules,
44✔
436
                  _.map(packageForceIncludes, whitelistedPackage => ({
44✔
437
                    external: whitelistedPackage
8✔
438
                  }))
44✔
439
                ),
44✔
440
                packagePath,
44✔
441
                nodeModulesRelativeDir,
44✔
442
                dependencyGraph,
44✔
443
                packageForceExcludes
44✔
444
              );
44✔
445
              removeExcludedModules.call(this, prodModules, packageForceExcludes);
44✔
446
              const relPath = path.relative(modulePath, path.dirname(packageJsonPath));
44✔
447
              addModulesToPackageJson(prodModules, modulePackage, relPath);
44✔
448
              this.serverless.utils.writeFileSync(modulePackageJson, JSON.stringify(modulePackage, null, 2));
44✔
449

44✔
450
              // GOOGLE: Copy modules only if not google-cloud-functions
44✔
451
              //         GCF Auto installs the package json
44✔
452
              if (isProviderGoogle(this.serverless)) {
44✔
453
                return BbPromise.resolve();
2✔
454
              }
2✔
455

42✔
456
              const startCopy = _.now();
42✔
457
              return BbPromise.try(() => {
42✔
458
                // Only copy dependency modules if demanded by packager
42✔
459
                if (packager.mustCopyModules) {
42✔
460
                  return BbPromise.fromCallback(callback =>
36✔
461
                    fse.copy(
36✔
462
                      path.join(compositeModulePath, 'node_modules'),
36✔
463
                      path.join(modulePath, 'node_modules'),
36✔
464
                      callback
36✔
465
                    )
36✔
466
                  );
36✔
467
                }
36✔
468
                return BbPromise.resolve();
6✔
469
              })
42✔
470
                .then(() =>
42✔
471
                  hasPackageLock
42✔
472
                    ? BbPromise.fromCallback(callback =>
12✔
473
                        fse.copy(
12✔
474
                          path.join(compositeModulePath, packager.lockfileName),
12✔
475
                          path.join(modulePath, packager.lockfileName),
12✔
476
                          callback
12✔
477
                        )
12✔
478
                      )
12✔
479
                    : BbPromise.resolve()
30✔
480
                )
42✔
481
                .tap(() => {
42✔
482
                  if (this.log) {
42✔
483
                    this.log.verbose(`Copy modules: ${modulePath} [${_.now() - startCopy} ms]`);
6✔
484
                  } else {
42✔
485
                    this.options.verbose &&
36✔
486
                      this.serverless.cli.log(`Copy modules: ${modulePath} [${_.now() - startCopy} ms]`);
36✔
487
                  }
36✔
488
                })
42✔
489
                .then(() => {
42✔
490
                  // Prune extraneous packages - removes not needed ones
42✔
491
                  const startPrune = _.now();
42✔
492
                  return packager.getPackagerVersion(modulePath).then(version => {
42✔
493
                    return packager.prune(modulePath, this.configuration.packagerOptions, version).tap(() => {
42✔
494
                      if (this.log) {
42✔
495
                        this.log.verbose(`Prune: ${modulePath} [${_.now() - startPrune} ms]`);
6✔
496
                      } else {
42✔
497
                        this.options.verbose &&
36✔
498
                          this.serverless.cli.log(`Prune: ${modulePath} [${_.now() - startPrune} ms]`);
36✔
499
                      }
36✔
500
                    });
42✔
501
                  });
42✔
502
                })
42✔
503
                .then(() => {
42✔
504
                  // Prune extraneous packages - removes not needed ones
42✔
505
                  const startRunScripts = _.now();
42✔
506
                  return packager.runScripts(modulePath, _.keys(packageScripts)).tap(() => {
42✔
507
                    if (this.log) {
42✔
508
                      this.log.verbose(`Run scripts: ${modulePath} [${_.now() - startRunScripts} ms]`);
6✔
509
                    } else {
42✔
510
                      this.options.verbose &&
36✔
511
                        this.serverless.cli.log(`Run scripts: ${modulePath} [${_.now() - startRunScripts} ms]`);
36✔
512
                    }
36✔
513
                  });
42✔
514
                });
42✔
515
            })
50✔
516
            .return();
50✔
517
        });
52✔
518
    });
56✔
519
  }
56✔
520
};
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc