Skip to content

Commit 9e28073

Browse files
committed
1.1 install express
1 parent c722f9e commit 9e28073

File tree

3 files changed

+139
-0
lines changed

3 files changed

+139
-0
lines changed

src/server.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const express = require("express");
2+
3+
const app = express();
4+
5+
const server = app.listen(process.env.PORT || 3000);
6+
7+
// -- DO NOT EDIT BELOW THIS LINE
8+
9+
module.exports = server;

test/dependency.test.js

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const assert = require("assert");
2+
3+
const { doesNotThrow, isModuleInstalled } = require("./utils");
4+
5+
describe("package.json", () => {
6+
// 1.1.
7+
it('should have "express" installed', async () => {
8+
assert.ok(
9+
await doesNotThrow(() =>
10+
isModuleInstalled({
11+
name: "express",
12+
type: "dependency"
13+
})
14+
)
15+
);
16+
});
17+
});

test/utils.js

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
const {
2+
promises: { readFile, readdir }
3+
} = require("fs");
4+
const { join } = require("path");
5+
6+
const getPackageJson = async (dir = process.cwd()) => {
7+
// load package.json file
8+
const pathToPackageJson = join(dir, "package.json");
9+
const packageJson = await readFile(pathToPackageJson, "utf8").catch(
10+
console.error
11+
);
12+
if (!packageJson) {
13+
throw new Error("Missing root package.json");
14+
}
15+
// parse as JSON
16+
const json = JSON.parse(packageJson);
17+
if (!json) {
18+
throw new Error("The package.json content looks invalid");
19+
}
20+
return json;
21+
};
22+
23+
exports.getPackageJson = getPackageJson;
24+
25+
const versionMatch = (current, expected) => {
26+
let currentSemver = current;
27+
if (["~", "^"].includes(current[0])) {
28+
currentSemver = current.substring(1);
29+
}
30+
return currentSemver === expected;
31+
};
32+
33+
/**
34+
* isModuleInstalled
35+
* @param { name, type } params
36+
* "name" - the name of the dependency
37+
* "type" - "dependency", "devDependency", "peerDependency"
38+
* @returns boolean
39+
*/
40+
const isModuleInstalled = async ({ name, type, version }) => {
41+
// 1. load package.json file
42+
const json = await getPackageJson();
43+
44+
// 2. verify package lists dependency by type
45+
let installCommand;
46+
let hasDependency;
47+
let currentVersion;
48+
49+
switch (type) {
50+
case "dependency":
51+
installCommand = "--save";
52+
hasDependency = !!json.dependencies && json.dependencies[name];
53+
currentVersion = json.dependencies[name];
54+
break;
55+
case "devDependency":
56+
installCommand = "--save-dev";
57+
hasDependency = !!json.devDependencies && json.devDependencies[name];
58+
currentVersion = json.devDependencies[name];
59+
break;
60+
case "peerDependency":
61+
throw new Error("Peer dependencies unsupported");
62+
default:
63+
throw new Error("Unsupported packaged type");
64+
}
65+
66+
if (!hasDependency) {
67+
throw new Error(`Run "npm install ${installCommand} ${name}"`);
68+
}
69+
70+
// 3. if version, check dependency version
71+
if (version && !versionMatch(currentVersion, version)) {
72+
throw new Error(
73+
`Dependency ${name} version ${currentVersion} does not match expected ${version}`
74+
);
75+
}
76+
77+
// 4. verify node_module installed
78+
const pathToNodeModule = join(process.cwd(), "node_modules", name);
79+
const hasNodeModules = await readdir(pathToNodeModule).catch(() => {
80+
throw new Error('Missing node_modules. Run "npm install"');
81+
});
82+
if (!hasNodeModules) {
83+
throw new Error('Missing node_modules. Run "npm install"');
84+
}
85+
86+
// 5. if version, has installed node_module version
87+
if (version) {
88+
const nodeModulePackageJson = await getPackageJson(pathToNodeModule);
89+
if (!versionMatch(nodeModulePackageJson.version, version)) {
90+
throw new Error(
91+
`Dependency ${name} version ${version} is not yet installed. Run "npm install"`
92+
);
93+
}
94+
}
95+
96+
return true;
97+
};
98+
99+
exports.isModuleInstalled = isModuleInstalled;
100+
101+
// created because assert.doesNotThrow not working predictably with async fns
102+
const doesNotThrow = async fn => {
103+
let result = true;
104+
try {
105+
await fn();
106+
} catch (error) {
107+
console.error(error);
108+
result = false;
109+
}
110+
return result;
111+
};
112+
113+
exports.doesNotThrow = doesNotThrow;

0 commit comments

Comments
 (0)