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

clay / claycli / 25125385992

29 Apr 2026 06:01PM UTC coverage: 64.054% (-28.0%) from 92.014%
25125385992

push

github

web-flow
🍕 Add clay vite — Vite ESM bundling pipeline (#239)

562 of 902 branches covered (62.31%)

Branch coverage included in aggregate %.

425 of 943 new or added lines in 16 files covered. (45.07%)

1097 of 1688 relevant lines covered (64.99%)

9.09 hits per line

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

97.62
/lib/cmd/vite/plugins/missing-module.js
1
'use strict';
2

3
const fs = require('fs');
13✔
4
const path = require('path');
13✔
5

6
const VIRTUAL_PREFIX = '\0clay-vite-missing:';
13✔
7

8
/**
9
 * Find the first existing file path among a list of candidates.
10
 * Returns undefined if none exist.
11
 *
12
 * @param {string} resolved  base resolved path (no extension)
13
 * @returns {string|undefined}
14
 */
15
function findExistingCandidate(resolved) {
16
  const candidates = [
4✔
17
    resolved,
18
    resolved + '.js',
19
    path.join(resolved, 'index.js'),
20
  ];
21

22
  return candidates.find(c => {
4✔
23
    try { return fs.statSync(c).isFile(); } catch (_) { return false; }
10✔
24
  });
25
}
26

27
/**
28
 * Returns true if a file is empty or unreadable.
29
 * Empty files should be stubbed: they produce MISSING_EXPORT warnings
30
 * from Rollup and an undefined default at runtime.
31
 *
32
 * @param {string} filepath
33
 * @returns {boolean}
34
 */
35
function isEmptyOrUnreadable(filepath) {
36
  try {
2✔
37
    return !fs.readFileSync(filepath, 'utf8').trim();
2✔
38
  } catch (_) {
NEW
39
    return true;
×
40
  }
41
}
42

43
/**
44
 * Vite plugin that silently stubs unresolvable relative imports.
45
 *
46
 * ── Why this exists ──────────────────────────────────────────────────────────
47
 *
48
 * The legacy Browserify pipeline ignored missing require() targets and produced
49
 * a bundle anyway (the missing module simply resolved to an empty object at
50
 * runtime).  Vite/Rollup errors hard on unresolvable imports by default.
51
 *
52
 * This plugin restores the lenient behaviour: if a relative import path does
53
 * not exist on disk, it is replaced with an empty ESM stub that exports
54
 * `undefined` as the default.  The browser simply receives `undefined` for
55
 * that import, which matches the historical Browserify behaviour.
56
 *
57
 * Never applies to node_modules imports — those must resolve correctly or fail
58
 * loudly to surface missing dependency installations.
59
 *
60
 * Runs with enforce:'pre' so it fires before Vite's resolver would hard-error.
61
 *
62
 * ── ESM migration note ───────────────────────────────────────────────────────
63
 *
64
 * This plugin exists because some legacy components import files that were
65
 * deleted or never created.  As components are migrated to ESM and cleaned up,
66
 * the number of stubs logged during the build should approach zero.  A zero
67
 * count means all imports are satisfied and this plugin becomes a no-op.
68
 */
69
/**
70
 * @returns {object} Vite plugin object
71
 */
72
function viteMissingModulePlugin() {
73
  return {
12✔
74
    name: 'clay-vite-missing-module',
75
    enforce: 'pre',
76

77
    resolveId(id, importer) {
78
      if (!importer) return null;
10✔
79
      if (!id.startsWith('.')) return null;
8✔
80

81
      // Strip Vite/Rollup internal query suffixes
82
      const cleanImporter = importer.replace(/\?.*$/, '').replace(/\0/g, '');
6✔
83

84
      if (!cleanImporter || !path.isAbsolute(cleanImporter)) return null;
6✔
85

86
      // Never touch node_modules imports
87
      if (cleanImporter.includes(`${path.sep}node_modules${path.sep}`)) return null;
5✔
88

89
      const resolved = path.resolve(path.dirname(cleanImporter), id);
4✔
90
      const existingFile = findExistingCandidate(resolved);
4✔
91

92
      if (!existingFile) {
4✔
93
        console.warn(
2✔
94
          `[clay vite] skipping missing module: ${id} ` +
95
          `(imported from ${path.relative(process.cwd(), cleanImporter)})`
96
        );
97
        return `${VIRTUAL_PREFIX}${id}`;
2✔
98
      }
99

100
      // Stub empty files too — see isEmptyOrUnreadable for rationale.
101
      if (isEmptyOrUnreadable(existingFile)) return `${VIRTUAL_PREFIX}${id}`;
2✔
102

103
      return null;
1✔
104
    },
105

106
    load(id) {
107
      if (id.startsWith(VIRTUAL_PREFIX)) {
2✔
108
        return 'export default undefined;';
1✔
109
      }
110

111
      return null;
1✔
112
    },
113
  };
114
}
115

116
module.exports = viteMissingModulePlugin;
13✔
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