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

serverless-heaven / serverless-webpack / 28932671810

08 Jul 2026 09:34AM UTC coverage: 90.515% (-2.4%) from 92.918%
28932671810

push

github

web-flow
Merge pull request #2431 from serverless-heaven/dependabot/npm_and_yarn/archiver-8.0.0

build(deps): bump archiver from 7.0.1 to 8.0.0

989 of 1157 branches covered (85.48%)

Branch coverage included in aggregate %.

2 of 2 new or added lines in 1 file covered. (100.0%)

55 existing lines in 7 files now uncovered.

2580 of 2786 relevant lines covered (92.61%)

27.25 hits per line

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

88.3
/lib/packExternalModules.js
1
const _ = require('lodash');
2✔
2
const path = require('node:path');
2✔
3
const fse = require('fs-extra');
2✔
4
const findWorkspaceRoot = require('find-yarn-workspace-root');
2✔
5

2✔
6
const Packagers = require('./packagers');
2✔
7
const { isProviderGoogle } = require('./utils');
2✔
8

2✔
9
function callWithOptionalCallback(fn, ...args) {
100✔
10
  return new Promise((resolve, reject) => {
100✔
11
    let settled = false;
100✔
12

100✔
13
    const callback = (error, result) => {
100✔
14
      settled = true;
82✔
15
      if (error) {
82✔
16
        reject(error);
2✔
17
        return;
2✔
18
      }
2✔
19
      resolve(result);
80✔
20
    };
100✔
21

100✔
22
    let result;
100✔
23
    try {
100✔
24
      result = fn(...args, callback);
100✔
25
    } catch (error) {
100✔
26
      reject(error);
2✔
27
      return;
2✔
28
    }
2✔
29

98✔
30
    if (result && typeof result.then === 'function') {
100✔
31
      result.then(
12✔
32
        value => {
12✔
33
          if (!settled) {
10✔
34
            resolve(value);
10✔
35
          }
10✔
36
        },
12✔
37
        error => {
12✔
38
          if (!settled) {
2✔
39
            reject(error);
2✔
40
          }
2✔
41
        }
2✔
42
      );
12✔
43
      return;
12✔
44
    }
12✔
45

86✔
46
    if (!settled && result !== undefined) {
100✔
47
      resolve(result);
4✔
48
    }
4✔
49
  });
100✔
50
}
100✔
51

2✔
52
function rebaseFileReferences(pathToPackageRoot, moduleVersion) {
294✔
53
  if (/^(?:file:[^/]{2}|\.\/|\.\.\/)/.test(moduleVersion)) {
294✔
54
    const filePath = _.replace(moduleVersion, /^file:/, '');
4✔
55
    return _.replace(
4✔
56
      `${_.startsWith(moduleVersion, 'file:') ? 'file:' : ''}${pathToPackageRoot}/${filePath}`,
4!
57
      /\\/g,
4✔
58
      '/'
4✔
59
    );
4✔
60
  }
4✔
61

290✔
62
  return moduleVersion;
290✔
63
}
290✔
64

2✔
65
/**
2✔
66
 * Add the given modules to a package json's dependencies.
2✔
67
 */
2✔
68
function addModulesToPackageJson(externalModules, packageJson, pathToPackageRoot) {
94✔
69
  _.forEach(externalModules.sort(), externalModule => {
94✔
70
    const splitModule = _.split(externalModule, '@');
294✔
71
    // If we have a scoped module we have to re-add the @
294✔
72
    if (_.startsWith(externalModule, '@')) {
294✔
73
      splitModule.splice(0, 1);
78✔
74
      splitModule[0] = `@${splitModule[0]}`;
78✔
75
    }
78✔
76
    let moduleVersion = _.join(_.tail(splitModule), '@');
294✔
77
    // We have to rebase file references to the target package.json
294✔
78
    moduleVersion = rebaseFileReferences(pathToPackageRoot, moduleVersion);
294✔
79
    packageJson.dependencies = packageJson.dependencies || {};
294✔
80
    packageJson.dependencies[_.first(splitModule)] = moduleVersion;
294✔
81
  });
94✔
82
}
94✔
83

2✔
84
/**
2✔
85
 * Remove a given list of excluded modules from a module list
2✔
86
 * @this - The active plugin instance
2✔
87
 */
2✔
88
function removeExcludedModules(modules, packageForceExcludes, log) {
96✔
89
  const excludedModules = _.remove(modules, externalModule => {
96✔
90
    const splitModule = _.split(externalModule, '@');
298✔
91
    // If we have a scoped module we have to re-add the @
298✔
92
    if (_.startsWith(externalModule, '@')) {
298✔
93
      splitModule.splice(0, 1);
78✔
94
      splitModule[0] = `@${splitModule[0]}`;
78✔
95
    }
78✔
96
    const moduleName = _.first(splitModule);
298✔
97
    return _.includes(packageForceExcludes, moduleName);
298✔
98
  });
96✔
99

96✔
100
  if (log && !_.isEmpty(excludedModules)) {
96✔
101
    if (this.log) {
2!
102
      this.log(`Excluding external modules: ${_.join(excludedModules, ', ')}`);
×
103
    } else {
2✔
104
      this.serverless.cli.log(`Excluding external modules: ${_.join(excludedModules, ', ')}`);
2✔
105
    }
2✔
106
  }
2✔
107
}
96✔
108

2✔
109
/**
2✔
110
 * Resolve the needed versions of production dependencies for external modules.
2✔
111
 * @this - The active plugin instance
2✔
112
 */
2✔
113
function getProdModules(externalModules, packagePath, nodeModulesRelativeDir, dependencyGraph, forceExcludes) {
110✔
114
  const packageJsonPath = path.join(process.cwd(), packagePath);
110✔
115
  const packageJson = require(packageJsonPath);
110✔
116
  const prodModules = [];
110✔
117

110✔
118
  // only process the module stated in dependencies section
110✔
119
  if (!packageJson.dependencies) {
110!
120
    return [];
×
121
  }
×
122

110✔
123
  // Get versions of all transient modules
110✔
124
  _.forEach(externalModules, module => {
110✔
125
    let moduleVersion = packageJson.dependencies[module.external];
308✔
126

308✔
127
    if (moduleVersion) {
308✔
128
      prodModules.push(`${module.external}@${moduleVersion}`);
282✔
129

282✔
130
      let nodeModulesBase = path.join(path.dirname(path.join(process.cwd(), packagePath)), 'node_modules');
282✔
131

282✔
132
      if (nodeModulesRelativeDir) {
282✔
133
        const customNodeModulesDir = path.join(process.cwd(), nodeModulesRelativeDir, 'node_modules');
12✔
134

12✔
135
        if (fse.pathExistsSync(customNodeModulesDir)) {
12✔
136
          nodeModulesBase = customNodeModulesDir;
12✔
137
        } else {
12!
138
          if (this.log) {
×
139
            this.log.warning(`${customNodeModulesDir} dose not exist. Please check nodeModulesRelativeDir setting`);
×
140
          } else {
×
141
            this.serverless.cli.log(
×
142
              `WARNING: ${customNodeModulesDir} dose not exist. Please check nodeModulesRelativeDir setting`
×
143
            );
×
144
          }
×
145
        }
×
146
      }
12✔
147

282✔
148
      // Check if the module has any peer dependencies and include them too
282✔
149
      try {
282✔
150
        const modulePackagePath = path.join(nodeModulesBase, module.external, 'package.json');
282✔
151

282✔
152
        const peerDependencies = require(modulePackagePath).peerDependencies;
282✔
153
        if (!_.isEmpty(peerDependencies)) {
282✔
154
          if (this.log) {
12!
155
            this.log.verbose(`Adding explicit peers for dependency ${module.external}`);
×
156
          } else {
12✔
157
            this.options.verbose && this.serverless.cli.log(`Adding explicit peers for dependency ${module.external}`);
12✔
158
          }
12✔
159

12✔
160
          const peerDependenciesMeta = require(modulePackagePath).peerDependenciesMeta;
12✔
161

12✔
162
          if (!_.isEmpty(peerDependenciesMeta)) {
12✔
163
            _.forEach(peerDependencies, (_value, key) => {
8✔
164
              if (peerDependenciesMeta[key] && peerDependenciesMeta[key].optional === true) {
12✔
165
                if (this.log) {
4!
166
                  this.log.verbose(
×
167
                    `Skipping peers dependency ${key} for dependency ${module.external} because it's optional`
×
168
                  );
×
169
                } else {
4✔
170
                  this.options.verbose &&
4✔
171
                    this.serverless.cli.log(
4✔
172
                      `Skipping peers dependency ${key} for dependency ${module.external} because it's optional`
4✔
173
                    );
4✔
174
                }
4✔
175
                _.unset(peerDependencies, key);
4✔
176
              }
4✔
177
            });
8✔
178
          }
8✔
179

12✔
180
          if (!_.isEmpty(peerDependencies)) {
12✔
181
            const peerModules = getProdModules.call(
12✔
182
              this,
12✔
183
              _.map(peerDependencies, (_value, key) => ({ external: key })),
12✔
184
              packagePath,
12✔
185
              nodeModulesRelativeDir,
12✔
186
              dependencyGraph,
12✔
187
              forceExcludes
12✔
188
            );
12✔
189
            Array.prototype.push.apply(prodModules, peerModules);
12✔
190
          }
12✔
191
        }
12✔
192
      } catch (_e) {
282✔
193
        if (this.log) {
122!
UNCOV
194
          this.log.warning(
×
UNCOV
195
            `Could not check for peer dependencies of ${module.external}. Set nodeModulesRelativeDir if node_modules is in different directory.`
×
UNCOV
196
          );
×
197
        } else {
122✔
198
          this.serverless.cli.log(
122✔
199
            `WARNING: Could not check for peer dependencies of ${module.external}. Set nodeModulesRelativeDir if node_modules is in different directory.`
122✔
200
          );
122✔
201
        }
122✔
202
      }
122✔
203
    } else {
308✔
204
      if (!packageJson.devDependencies?.[module.external]) {
26✔
205
        // Add transient dependencies if they appear not in the service's dev dependencies
16✔
206
        const originInfo = _.get(dependencyGraph, 'dependencies', {})[module.origin] || {};
16✔
207
        moduleVersion = _.get(_.get(originInfo, 'dependencies', {})[module.external], 'version');
16✔
208
        if (!moduleVersion) {
16✔
209
          moduleVersion = _.get(dependencyGraph, ['dependencies', module.external, 'version']);
16✔
210
        }
16✔
211
        if (!moduleVersion) {
16✔
212
          if (this.log) {
12!
213
            this.log.warning(`Could not determine version of module ${module.external}`);
×
214
          } else {
12✔
215
            this.serverless.cli.log(`WARNING: Could not determine version of module ${module.external}`);
12✔
216
          }
12✔
217
        }
12✔
218
        prodModules.push(moduleVersion ? `${module.external}@${moduleVersion}` : module.external);
16✔
219
      } else if (packageJson.devDependencies?.[module.external] && !_.includes(forceExcludes, module.external)) {
26✔
220
        // To minimize the chance of breaking setups we whitelist packages available on AWS here. These are due to the previously missing check
6✔
221
        // most likely set in devDependencies and should not lead to an error now.
6✔
222
        const ignoredDevDependencies = ['aws-sdk'];
6✔
223

6✔
224
        if (!_.includes(ignoredDevDependencies, module.external)) {
6✔
225
          // Runtime dependency found in devDependencies but not forcefully excluded
2✔
226
          if (this.log) {
2!
227
            this.log.error(
×
228
              `Runtime dependency '${module.external}' found in devDependencies. Move it to dependencies or use forceExclude to explicitly exclude it.`
×
229
            );
×
230
          } else {
2✔
231
            this.serverless.cli.log(
2✔
232
              `ERROR: Runtime dependency '${module.external}' found in devDependencies. Move it to dependencies or use forceExclude to explicitly exclude it.`
2✔
233
            );
2✔
234
          }
2✔
235
          throw new this.serverless.classes.Error(`Serverless-webpack dependency error: ${module.external}.`);
2✔
236
        }
2✔
237
        if (this.log) {
6!
UNCOV
238
          this.log.verbose(
×
UNCOV
239
            `Runtime dependency '${module.external}' found in devDependencies. It has been excluded automatically.`
×
UNCOV
240
          );
×
241
        } else {
6✔
242
          this.options.verbose &&
4✔
243
            this.serverless.cli.log(
4✔
244
              `INFO: Runtime dependency '${module.external}' found in devDependencies. It has been excluded automatically.`
4✔
245
            );
4✔
246
        }
4✔
247
      }
6✔
248
    }
26✔
249
  });
110✔
250

110✔
251
  return prodModules;
110✔
252
}
110✔
253

2✔
254
module.exports = {
2✔
255
  /**
2✔
256
   * We need a performant algorithm to install the packages for each single
2✔
257
   * function (in case we package individually).
2✔
258
   * (1) We fetch ALL packages needed by ALL functions in a first step
2✔
259
   * and use this as a base npm checkout. The checkout will be done to a
2✔
260
   * separate temporary directory with a package.json that contains everything.
2✔
261
   * (2) For each single compile we copy the whole node_modules to the compile
2✔
262
   * directory and create a (function) compile specific package.json and store
2✔
263
   * it in the compile directory. Now we start npm again there, and npm will just
2✔
264
   * remove the superfluous packages and optimize the remaining dependencies.
2✔
265
   * This will utilize the npm cache at its best and give us the needed results
2✔
266
   * and performance.
2✔
267
   */
2✔
268
  async packExternalModules() {
2✔
269
    if (this.skipCompile) {
60✔
270
      return;
2✔
271
    }
2✔
272

58✔
273
    const stats = this.compileStats;
58✔
274

58✔
275
    const includes = this.configuration.includeModules;
58✔
276

58✔
277
    if (!includes) {
60✔
278
      return;
2✔
279
    }
2✔
280
    if (this.log) {
60!
UNCOV
281
      this.log.verbose('Packing external modules');
×
UNCOV
282
      this.progress.get('webpack').notice('[Webpack] Packing external modules');
×
UNCOV
283
    }
✔
284

56✔
285
    // Read plugin configuration
56✔
286
    const packageForceIncludes = _.get(includes, 'forceInclude', []);
56✔
287
    const packageForceExcludes = _.get(includes, 'forceExclude', []);
56✔
288
    const packagePath = includes.packagePath || './package.json';
60✔
289
    const nodeModulesRelativeDir = includes.nodeModulesRelativeDir;
60✔
290
    const packageJsonPath = path.join(process.cwd(), packagePath);
60✔
291
    const packageScripts = _.reduce(
60✔
292
      this.configuration.packagerOptions.scripts || [],
60✔
293
      (__, script, index) => {
60✔
294
        __[`script${index}`] = script;
×
295
        return __;
×
296
      },
60✔
297
      {}
60✔
298
    );
60✔
299

60✔
300
    // Determine and create packager
60✔
301
    const packager = Packagers.get.call(this, this.configuration.packager);
60✔
302

60✔
303
    // Fetch needed original package.json sections
60✔
304
    const sectionNames = packager.copyPackageSectionNames(this.configuration.packagerOptions);
60✔
305
    const packageJson = this.serverless.utils.readFileSync(packageJsonPath);
60✔
306
    const packageSections = _.pick(packageJson, sectionNames);
60✔
307
    if (!_.isEmpty(packageSections)) {
60✔
308
      if (this.log) {
4!
309
        this.log.verbose(`Using package.json sections ${_.join(_.keys(packageSections), ', ')}`);
×
310
      } else {
4✔
311
        this.options.verbose &&
4✔
312
          this.serverless.cli.log(`Using package.json sections ${_.join(_.keys(packageSections), ', ')}`);
4✔
313
      }
4✔
314
    }
4✔
315

56✔
316
    // Get first level dependency graph
56✔
317
    if (this.log) {
60!
UNCOV
318
      this.log.verbose(`Fetch dependency graph from ${packageJsonPath}`);
×
319
    } else {
60✔
320
      this.options.verbose && this.serverless.cli.log(`Fetch dependency graph from ${packageJsonPath}`);
56✔
321
    }
56✔
322

56✔
323
    const dependencyGraph = await packager.getProdDependencies(
56✔
324
      path.dirname(packageJsonPath),
56✔
325
      1,
56✔
326
      this.configuration.packagerOptions
56✔
327
    );
56✔
328
    const problems = _.get(dependencyGraph, 'problems', []);
54✔
329
    if (this.options.verbose && !_.isEmpty(problems)) {
60✔
330
      if (this.log) {
2!
331
        this.log.verbose(`Ignoring ${_.size(problems)} NPM errors:`);
×
332
      } else {
2✔
333
        this.serverless.cli.log(`Ignoring ${_.size(problems)} NPM errors:`);
2✔
334
      }
2✔
335
      _.forEach(problems, problem => {
2✔
336
        if (this.log) {
4!
337
          this.log.verbose(`=> ${problem}`);
×
338
        } else {
4✔
339
          this.serverless.cli.log(`=> ${problem}`);
4✔
340
        }
4✔
341
      });
2✔
342
    }
2✔
343

54✔
344
    // (1) Generate dependency composition
54✔
345
    const compositeModules = _.uniq(
54✔
346
      _.flatMap(stats.stats, compileStats => {
54✔
347
        const externalModules = _.concat(
54✔
348
          compileStats.externalModules,
54✔
349
          _.map(packageForceIncludes, whitelistedPackage => ({
54✔
350
            external: whitelistedPackage
6✔
351
          }))
54✔
352
        );
54✔
353
        return getProdModules.call(
54✔
354
          this,
54✔
355
          externalModules,
54✔
356
          packagePath,
54✔
357
          nodeModulesRelativeDir,
54✔
358
          dependencyGraph,
54✔
359
          packageForceExcludes
54✔
360
        );
54✔
361
      })
54✔
362
    );
54✔
363
    removeExcludedModules.call(this, compositeModules, packageForceExcludes, true);
54✔
364

54✔
365
    if (_.isEmpty(compositeModules)) {
60✔
366
      // The compiled code does not reference any external modules at all
2✔
367
      if (this.log) {
2!
368
        this.log('No external modules needed');
×
369
      } else {
2✔
370
        this.serverless.cli.log('No external modules needed');
2✔
371
      }
2✔
372
      return;
2✔
373
    }
2✔
374

50✔
375
    // (1.a) Install all needed modules
50✔
376
    const compositeModulePath = path.join(this.webpackOutputPath, 'dependencies');
50✔
377
    const compositePackageJson = path.join(compositeModulePath, 'package.json');
50✔
378

50✔
379
    // (1.a.1) Create a package.json
50✔
380
    const compositePackage = _.defaults(
50✔
381
      {
50✔
382
        name: this.serverless.service.service,
50✔
383
        version: '1.0.0',
50✔
384
        description: `Packaged externals for ${this.serverless.service.service}`,
50✔
385
        private: true,
50✔
386
        scripts: packageScripts
50✔
387
      },
50✔
388
      packageSections
50✔
389
    );
50✔
390
    const relPath = path.relative(compositeModulePath, path.dirname(packageJsonPath));
50✔
391
    addModulesToPackageJson(compositeModules, compositePackage, relPath);
50✔
392
    this.serverless.utils.writeFileSync(compositePackageJson, JSON.stringify(compositePackage, null, 2));
50✔
393

50✔
394
    // (1.a.2) Copy package-lock.json if it exists, to prevent unwanted upgrades
50✔
395
    const packagerOptions = this.configuration.packagerOptions || {};
60!
396
    const packageLockPath = path.join(
60✔
397
      findWorkspaceRoot(path.dirname(packageJsonPath)) || path.dirname(packageJsonPath),
60✔
398
      packagerOptions.lockFile || packager.lockfileName
60✔
399
    );
60✔
400
    let hasPackageLock = false;
60✔
401
    const exists = await callWithOptionalCallback(fse.pathExists, packageLockPath);
60✔
402
    if (exists) {
60✔
403
      if (this.log) {
14!
UNCOV
404
        this.log('Package lock found - Using locked versions');
×
405
      } else {
14✔
406
        this.serverless.cli.log('Package lock found - Using locked versions');
14✔
407
      }
14✔
408
      try {
14✔
409
        let packageLockFile = this.serverless.utils.readFileSync(packageLockPath);
14✔
410
        packageLockFile = packager.rebaseLockfile(relPath, packageLockFile);
14✔
411
        if (_.isObject(packageLockFile)) {
14✔
412
          packageLockFile = JSON.stringify(packageLockFile, null, 2);
10✔
413
        }
10✔
414

10✔
415
        this.serverless.utils.writeFileSync(path.join(compositeModulePath, packager.lockfileName), packageLockFile);
10✔
416
        hasPackageLock = true;
10✔
417
      } catch (err) {
14✔
418
        if (this.log) {
4!
419
          this.log.warning(`Could not read lock file: ${err.message}`);
×
420
        } else {
4✔
421
          this.serverless.cli.log(`Warning: Could not read lock file: ${err.message}`);
4✔
422
        }
4✔
423
      }
4✔
424
    }
14✔
425

46✔
426
    const start = _.now();
46✔
427
    if (this.log) {
60!
UNCOV
428
      this.log(`Packing external modules: ${compositeModules.join(', ')}`);
×
429
    } else {
60✔
430
      this.serverless.cli.log(`Packing external modules: ${compositeModules.join(', ')}`);
46✔
431
    }
46✔
432

46✔
433
    const compositePackagerVersion = await packager.getPackagerVersion(compositeModulePath);
46✔
434
    await packager.install(compositeModulePath, this.configuration.packagerOptions, compositePackagerVersion);
46✔
435
    if (this.log) {
60!
UNCOV
436
      this.log.verbose(`Package took [${_.now() - start} ms]`);
×
437
    } else {
60✔
438
      this.options.verbose && this.serverless.cli.log(`Package took [${_.now() - start} ms]`);
44✔
439
    }
44✔
440

44✔
441
    for (const compileStats of stats.stats) {
44✔
442
      const modulePath = compileStats.outputPath;
44✔
443

44✔
444
      // Create package.json
44✔
445
      const modulePackageJson = path.join(modulePath, 'package.json');
44✔
446
      const modulePackage = _.defaults(
44✔
447
        {
44✔
448
          name: this.serverless.service.service,
44✔
449
          version: '1.0.0',
44✔
450
          description: `Packaged externals for ${this.serverless.service.service}`,
44✔
451
          private: true,
44✔
452
          scripts: packageScripts,
44✔
453
          dependencies: {}
44✔
454
        },
44✔
455
        packageSections
44✔
456
      );
44✔
457
      const prodModules = getProdModules.call(
44✔
458
        this,
44✔
459
        _.concat(
44✔
460
          compileStats.externalModules,
44✔
461
          _.map(packageForceIncludes, whitelistedPackage => ({
44✔
462
            external: whitelistedPackage
6✔
463
          }))
44✔
464
        ),
44✔
465
        packagePath,
44✔
466
        nodeModulesRelativeDir,
44✔
467
        dependencyGraph,
44✔
468
        packageForceExcludes
44✔
469
      );
44✔
470
      removeExcludedModules.call(this, prodModules, packageForceExcludes);
44✔
471
      const moduleRelPath = path.relative(modulePath, path.dirname(packageJsonPath));
44✔
472
      addModulesToPackageJson(prodModules, modulePackage, moduleRelPath);
44✔
473
      this.serverless.utils.writeFileSync(modulePackageJson, JSON.stringify(modulePackage, null, 2));
44✔
474

44✔
475
      // GOOGLE: Copy modules only if not google-cloud-functions
44✔
476
      //         GCF Auto installs the package json
44✔
477
      if (isProviderGoogle(this.serverless)) {
44✔
478
        continue;
2✔
479
      }
2✔
480

42✔
481
      const startCopy = _.now();
42✔
482
      // Only copy dependency modules if demanded by packager
42✔
483
      if (packager.mustCopyModules) {
44✔
484
        await callWithOptionalCallback(
40✔
485
          fse.copy,
40✔
486
          path.join(compositeModulePath, 'node_modules'),
40✔
487
          path.join(modulePath, 'node_modules')
40✔
488
        );
40✔
489
      }
38✔
490
      if (hasPackageLock) {
44✔
491
        await callWithOptionalCallback(
10✔
492
          fse.copy,
10✔
493
          path.join(compositeModulePath, packager.lockfileName),
10✔
494
          path.join(modulePath, packager.lockfileName)
10✔
495
        );
10✔
496
      }
10✔
497
      if (this.log) {
44!
UNCOV
498
        this.log.verbose(`Copy modules: ${modulePath} [${_.now() - startCopy} ms]`);
×
499
      } else {
44✔
500
        this.options.verbose && this.serverless.cli.log(`Copy modules: ${modulePath} [${_.now() - startCopy} ms]`);
40✔
501
      }
40✔
502

40✔
503
      // Prune extraneous packages - removes not needed ones
40✔
504
      const startPrune = _.now();
40✔
505
      const modulePackagerVersion = await packager.getPackagerVersion(modulePath);
40✔
506
      await packager.prune(modulePath, this.configuration.packagerOptions, modulePackagerVersion);
40✔
507
      if (this.log) {
44!
UNCOV
508
        this.log.verbose(`Prune: ${modulePath} [${_.now() - startPrune} ms]`);
×
509
      } else {
44✔
510
        this.options.verbose && this.serverless.cli.log(`Prune: ${modulePath} [${_.now() - startPrune} ms]`);
40✔
511
      }
40✔
512

40✔
513
      // Run package scripts after prune
40✔
514
      const startRunScripts = _.now();
40✔
515
      await packager.runScripts(modulePath, _.keys(packageScripts));
40✔
516
      if (this.log) {
44!
UNCOV
517
        this.log.verbose(`Run scripts: ${modulePath} [${_.now() - startRunScripts} ms]`);
×
518
      } else {
44✔
519
        this.options.verbose && this.serverless.cli.log(`Run scripts: ${modulePath} [${_.now() - startRunScripts} ms]`);
40✔
520
      }
40✔
521
    }
44✔
522
  }
42✔
523
};
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc