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

pmcelhaney / counterfact / 3596104599

pending completion
3596104599

push

github

GitHub
Update dependency fs-extra to v11

380 of 401 branches covered (94.76%)

Branch coverage included in aggregate %.

1777 of 1999 relevant lines covered (88.89%)

21.89 hits per line

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

89.92
/src/server/module-loader.js
1
import fs from "node:fs/promises";
1✔
2
import { existsSync } from "node:fs";
1✔
3
import nodePath from "node:path";
1✔
4
import { once } from "node:events";
1✔
5

1✔
6
import chokidar from "chokidar";
1✔
7

1✔
8
import { ContextRegistry } from "./context-registry.js";
1✔
9

1✔
10
export class ModuleLoader extends EventTarget {
1✔
11
  basePath;
1✔
12

7✔
13
  registry;
7✔
14

7✔
15
  watcher;
7✔
16

7✔
17
  contextRegistry;
1✔
18

1✔
19
  constructor(basePath, registry, contextRegistry = new ContextRegistry()) {
1✔
20
    super();
7✔
21
    this.basePath = basePath;
7✔
22
    this.registry = registry;
7✔
23
    this.contextRegistry = contextRegistry;
7✔
24
  }
7✔
25

1✔
26
  async watch() {
1✔
27
    this.watcher = chokidar
5✔
28
      .watch(`${this.basePath}/**/*.{js,mjs,ts,mts}`)
5✔
29
      .on("all", (eventName, pathName) => {
5✔
30
        if (!["add", "change", "unlink"].includes(eventName)) {
8!
31
          return;
×
32
        }
×
33

8✔
34
        const parts = nodePath.parse(pathName.replace(this.basePath, ""));
8✔
35
        const url = nodePath.normalize(
8✔
36
          `/${nodePath.join(parts.dir, parts.name)}`
8✔
37
        );
8✔
38

8✔
39
        if (eventName === "unlink") {
8✔
40
          this.registry.remove(url);
1✔
41
          this.dispatchEvent(new Event("remove"), pathName);
1✔
42
        }
1✔
43

8✔
44
        // eslint-disable-next-line node/no-unsupported-features/es-syntax, import/no-dynamic-require
8✔
45
        import(`${pathName}?cacheBust=${Date.now()}`)
8✔
46
          // eslint-disable-next-line promise/prefer-await-to-then
8✔
47
          .then((endpoint) => {
8✔
48
            this.dispatchEvent(new Event(eventName), pathName);
8✔
49

8✔
50
            if (pathName.includes("$.context")) {
8!
51
              this.contextRegistry.update(parts.dir, endpoint.default);
×
52

×
53
              return "context";
×
54
            }
×
55

8✔
56
            this.registry.add(url, endpoint);
8✔
57

8✔
58
            return "path";
8✔
59
          })
8✔
60
          // eslint-disable-next-line promise/prefer-await-to-then
8✔
61
          .catch((error) => {
8✔
62
            throw error;
×
63
          });
×
64
      });
8✔
65
    await once(this.watcher, "ready");
5✔
66
  }
5✔
67

1✔
68
  async stopWatching() {
1✔
69
    await this.watcher?.close();
5✔
70
  }
5✔
71

1✔
72
  async load(directory = "") {
1✔
73
    if (!existsSync(nodePath.join(this.basePath, directory))) {
11!
74
      throw new Error(`Directory does not exist ${this.basePath}`);
×
75
    }
×
76

11✔
77
    const files = await fs.readdir(nodePath.join(this.basePath, directory), {
11✔
78
      withFileTypes: true,
11✔
79
    });
11✔
80

11✔
81
    const imports = files.flatMap(async (file) => {
11✔
82
      const extension = file.name.split(".").at(-1);
10✔
83

10✔
84
      if (file.isDirectory()) {
10✔
85
        await this.load(nodePath.join(directory, file.name));
10✔
86

10✔
87
        return;
10✔
88
      }
10✔
89

10✔
90
      if (!["js", "mjs", "ts", "mts"].includes(extension)) {
10✔
91
        return;
10✔
92
      }
10✔
93

10✔
94
      // eslint-disable-next-line node/no-unsupported-features/es-syntax, import/no-dynamic-require
10✔
95
      const endpoint = await import(
10✔
96
        nodePath.join(this.basePath, directory, file.name)
10✔
97
      );
10✔
98

10✔
99
      if (file.name.includes("$.context")) {
15✔
100
        this.contextRegistry.add(`/${directory}`, endpoint.default);
8✔
101
      } else {
8✔
102
        this.registry.add(
8✔
103
          `/${nodePath.join(directory, nodePath.parse(file.name).name)}`,
8✔
104
          endpoint
8✔
105
        );
8✔
106
      }
8✔
107
    });
15✔
108

11✔
109
    await Promise.all(imports);
11✔
110
  }
11✔
111
}
1✔
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

© 2025 Coveralls, Inc