Skip to content

Commit 372a9d4

Browse files
committed
feat: support PackageJson~read
1 parent b78f6b9 commit 372a9d4

File tree

3 files changed

+133
-4
lines changed

3 files changed

+133
-4
lines changed

README.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,22 @@ end
5656
package_json.manager.run("lint", ["--fix"])
5757
```
5858

59-
The `PackageJson` class represents a `package.json` on disk within a directory,
60-
creating the file if it does not already exist.
61-
62-
Because it is expected that the `package.json` might be changed by external
59+
The `PackageJson` class represents a `package.json` on disk within a directory;
60+
because it is expected that the `package.json` might be changed by external
6361
sources such as package managers, `PackageJson` reads and writes to and from the
6462
`package.json` as needed rather than representing it in memory.
6563

64+
You can initialize a `PackageJson` with either `new` or `read` depending on if
65+
you want to ensure the `package.json` exists or throw if it doesn't:
66+
67+
```ruby
68+
# this will create the `package.json` if it does not exist
69+
PackageJson.new(:npm, "path/to/directory")
70+
71+
# this will error if the `package.json` does not exist
72+
PackageJson.read("path/to/directory", :npm)
73+
```
74+
6675
A `PackageJson` also comes with a `manager` that can be used to manage
6776
dependencies and run scripts. The manager will be inferred by the
6877
[`packageManager`](https://nodejs.org/api/packages.html#packagemanager) property

lib/package_json.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ class NotImplementedError < Error; end
1414

1515
attr_reader :manager, :path
1616

17+
def self.read(path_to_directory = Dir.pwd, fallback_manager = :npm)
18+
unless File.exist?("#{path_to_directory}/package.json")
19+
raise Error, "#{path_to_directory} does not contain a package.json"
20+
end
21+
22+
new(fallback_manager, path_to_directory)
23+
end
24+
1725
def initialize(fallback_manager = :npm, path_to_directory = Dir.pwd)
1826
@path = path_to_directory
1927

spec/package_json_spec.rb

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,118 @@
99
expect(PackageJson::VERSION).not_to be_nil
1010
end
1111

12+
describe ".read" do
13+
context "when the package.json does not exist" do
14+
it "raises an error" do
15+
expect { described_class.read }.to raise_error(
16+
PackageJson::Error, "#{Dir.pwd} does not contain a package.json"
17+
)
18+
end
19+
end
20+
21+
context "when the package.json already exists with the packageManager property" do
22+
it "does not error" do
23+
with_package_json_file({ "version" => "1.0.0" }) do
24+
expect { described_class.new }.not_to raise_error
25+
end
26+
end
27+
28+
it "uses the packageManager property" do
29+
with_package_json_file({ "version" => "1.0.0", "packageManager" => "pnpm" }) do
30+
package_json = described_class.new
31+
32+
expect(package_json.manager).to be_a PackageJson::Managers::PnpmLike
33+
end
34+
end
35+
36+
it "ignores the fallback manager" do
37+
with_package_json_file({ "version" => "1.0.0", "packageManager" => "pnpm" }) do
38+
package_json = described_class.new(:yarn_classic)
39+
40+
expect(package_json.manager).to be_a PackageJson::Managers::PnpmLike
41+
end
42+
end
43+
44+
it "supports having a version specified" do
45+
with_package_json_file({ "version" => "1.0.0", "packageManager" => "[email protected]" }) do
46+
package_json = described_class.new
47+
48+
expect(package_json.manager).to be_a PackageJson::Managers::PnpmLike
49+
end
50+
end
51+
52+
it "requires a major version for yarn" do
53+
with_package_json_file({ "version" => "1.0.0", "packageManager" => "yarn" }) do
54+
expect { described_class.new }.to raise_error(PackageJson::Error, "a major version must be present for Yarn")
55+
end
56+
end
57+
58+
it "only supports yarn v1" do
59+
with_package_json_file({ "version" => "1.0.0", "packageManager" => "yarn@2" }) do
60+
expect { described_class.new }.to raise_error(PackageJson::Error, "only Yarn classic is supported")
61+
end
62+
end
63+
64+
it "supports a full version being specified for yarn" do
65+
with_package_json_file({ "version" => "1.0.0", "packageManager" => "[email protected]" }) do
66+
package_json = described_class.new
67+
68+
expect(package_json.manager).to be_a PackageJson::Managers::YarnClassicLike
69+
end
70+
end
71+
72+
it "does not change the packageManager property" do
73+
with_package_json_file({ "version" => "1.0.0", "packageManager" => "pnpm" }) do
74+
described_class.new(:yarn_classic)
75+
76+
expect_package_json_with_content({ "version" => "1.0.0", "packageManager" => "pnpm" })
77+
end
78+
end
79+
80+
it "raises an error if the package manager is not supported" do
81+
with_package_json_file({ "version" => "1.0.0", "packageManager" => "unknown" }) do
82+
expect { described_class.new }.to raise_error(
83+
PackageJson::Error,
84+
'unsupported package manager "unknown"'
85+
)
86+
end
87+
end
88+
end
89+
90+
context "when the package.json already exists without the packageManager property" do
91+
it "does not error" do
92+
with_package_json_file({ "version" => "1.0.0" }) do
93+
expect { described_class.new }.not_to raise_error
94+
end
95+
end
96+
97+
it "uses the fallback manager" do
98+
with_package_json_file({ "version" => "1.0.0" }) do
99+
package_json = described_class.new(:yarn_classic)
100+
101+
expect(package_json.manager).to be_a PackageJson::Managers::YarnClassicLike
102+
end
103+
end
104+
105+
it "does not add the packageManager property" do
106+
with_package_json_file({ "version" => "1.0.0" }) do
107+
described_class.new(:yarn_classic)
108+
109+
expect_package_json_with_content({ "version" => "1.0.0" })
110+
end
111+
end
112+
113+
it "raises an error if the fallback manager is not supported" do
114+
with_package_json_file({ "version" => "1.0.0" }) do
115+
expect { described_class.new(:unknown) }.to raise_error(
116+
PackageJson::Error,
117+
'unsupported package manager "unknown"'
118+
)
119+
end
120+
end
121+
end
122+
end
123+
12124
describe ".new" do
13125
context "when the package.json does not exist" do
14126
it "does not error" do

0 commit comments

Comments
 (0)