line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Mojo::Alien::npm; |
2
|
10
|
|
|
10
|
|
992790
|
use Mojo::Base -base; |
|
10
|
|
|
|
|
54
|
|
|
10
|
|
|
|
|
82
|
|
3
|
|
|
|
|
|
|
|
4
|
10
|
|
|
10
|
|
1984
|
use Carp qw(croak); |
|
10
|
|
|
|
|
23
|
|
|
10
|
|
|
|
|
527
|
|
5
|
10
|
|
|
10
|
|
1680
|
use File::chdir; |
|
10
|
|
|
|
|
7824
|
|
|
10
|
|
|
|
|
938
|
|
6
|
10
|
|
|
10
|
|
4253
|
use Mojo::File qw(path); |
|
10
|
|
|
|
|
255584
|
|
|
10
|
|
|
|
|
763
|
|
7
|
10
|
|
|
10
|
|
4840
|
use Mojo::JSON qw(decode_json false); |
|
10
|
|
|
|
|
192856
|
|
|
10
|
|
|
|
|
1167
|
|
8
|
|
|
|
|
|
|
|
9
|
10
|
|
50
|
10
|
|
111
|
use constant DEBUG => ($ENV{MOJO_NPM_DEBUG} || $ENV{MOJO_WEBPACK_DEBUG}) && 1; |
|
10
|
|
|
|
|
23
|
|
|
10
|
|
|
|
|
13333
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
has binary => sub { |
12
|
|
|
|
|
|
|
my $self = shift; |
13
|
|
|
|
|
|
|
return $ENV{MOJO_NPM_BINARY} ? $ENV{MOJO_NPM_BINARY} : 'npm'; |
14
|
|
|
|
|
|
|
}; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
has config => sub { path->to_abs->child('package.json') }; |
17
|
|
|
|
|
|
|
has mode => sub { $ENV{NODE_ENV} || 'development' }; |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
sub dependencies { |
20
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
21
|
0
|
0
|
|
|
|
|
croak "Can't get dependency info without package.json" unless -r $self->config; |
22
|
|
|
|
|
|
|
|
23
|
0
|
0
|
|
|
|
|
my @args = $self->binary eq 'pnpm' ? qw(ls --json --silent) : qw(ls --json --parseable --silent); |
24
|
0
|
|
|
|
|
|
my $dependencies; |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
eval { |
27
|
0
|
|
|
|
|
|
my $NPM = $self->_run(@args); |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
# "WARN" might come from pnpm, and it also returns an array-ref |
30
|
0
|
|
|
|
|
|
$dependencies = decode_json(join '', grep { !/WARN/ } <$NPM>); |
|
0
|
|
|
|
|
|
|
31
|
0
|
0
|
|
|
|
|
$dependencies = $dependencies->[0] if ref $dependencies eq 'ARRAY'; |
32
|
0
|
0
|
|
|
|
|
$dependencies = {map { %{$dependencies->{$_} || {}} } qw(devDependencies dependencies)}; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
33
|
0
|
0
|
|
|
|
|
} or do { |
34
|
0
|
|
|
|
|
|
croak sprintf '%s failed: %s', join(' ', $self->binary, @args), $@; |
35
|
|
|
|
|
|
|
}; |
36
|
|
|
|
|
|
|
|
37
|
0
|
|
|
|
|
|
my $package = decode_json $self->config->slurp; |
38
|
0
|
|
|
|
|
|
my %types = (devDependencies => 'dev', dependencies => 'prod', optionalDependencies => 'optional'); |
39
|
0
|
|
|
|
|
|
for my $type (qw(optionalDependencies devDependencies dependencies)) { |
40
|
0
|
|
|
|
|
|
for my $name (keys %{$package->{$type}}) { |
|
0
|
|
|
|
|
|
|
41
|
0
|
|
|
|
|
|
$dependencies->{$name}{required} = $package->{$type}{$name}; |
42
|
0
|
|
|
|
|
|
$dependencies->{$name}{type} = $types{$type}; |
43
|
0
|
|
0
|
|
|
|
$dependencies->{$name}{version} //= ''; |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
0
|
|
|
|
|
|
return $dependencies; |
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
sub init { |
51
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
52
|
0
|
0
|
|
|
|
|
return $self if -r $self->config; |
53
|
0
|
|
|
|
|
|
$self->_run(qw(init -y)); |
54
|
0
|
0
|
|
|
|
|
croak "$self->{basename} init failed: @{[$self->config]} was not generated." unless -r $self->config; |
|
0
|
|
|
|
|
|
|
55
|
0
|
|
|
|
|
|
return $self; |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
sub install { |
59
|
0
|
|
|
0
|
1
|
|
my ($self, $name, $info) = @_; |
60
|
0
|
0
|
|
|
|
|
croak "Can't install packages without package.json" unless -w $self->config; |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
# Install everything |
63
|
0
|
0
|
|
|
|
|
do { $self->_run('install'); return $self } unless $name; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# Install specific package |
66
|
0
|
0
|
|
|
|
|
$name = sprintf '%s@%s', $name, $info->{version} if $info->{version}; |
67
|
0
|
|
0
|
|
|
|
my $type = sprintf '--save-%s', $info->{type} || 'dev'; |
68
|
0
|
|
|
|
|
|
$self->_run('install', $name, $type); |
69
|
0
|
|
|
|
|
|
return $self; |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
sub _run { |
73
|
0
|
|
|
0
|
|
|
my $self = shift; |
74
|
0
|
|
|
|
|
|
my @cmd = ($self->binary, @_); |
75
|
0
|
|
0
|
|
|
|
$self->{basename} ||= path($cmd[0])->basename; |
76
|
0
|
|
|
|
|
|
local $CWD = $self->config->dirname->to_string; |
77
|
0
|
|
|
|
|
|
local $ENV{NODE_ENV} = $self->mode; |
78
|
0
|
|
|
|
|
|
warn "[NPM] cd $CWD && @cmd\n" if DEBUG; |
79
|
0
|
0
|
|
|
|
|
open my $NPM, '-|', @cmd or die "Can't fork @cmd: $!"; |
80
|
0
|
0
|
|
|
|
|
return $NPM if defined wantarray; |
81
|
0
|
|
|
|
|
|
map { DEBUG && print } <$NPM>; |
|
0
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
# This is a utility function for the unit tests |
85
|
|
|
|
|
|
|
sub _setup_working_directory { |
86
|
0
|
|
|
0
|
|
|
my ($class, $dir) = @_; |
87
|
0
|
0
|
|
0
|
|
|
my $remove_tree = $ENV{MOJO_NPM_CLEAN} ? 'remove_tree' : sub { }; |
88
|
0
|
0
|
|
|
|
|
chdir(my $work_dir = path($dir ? $dir : ('local', path($0)->basename))->to_abs->tap($remove_tree)->make_path) |
|
|
0
|
|
|
|
|
|
89
|
|
|
|
|
|
|
or die "Couldn't set up working directory: $!"; |
90
|
0
|
0
|
0
|
|
|
|
symlink $work_dir->dirname->child('node_modules')->make_path, 'node_modules' |
91
|
|
|
|
|
|
|
or warn "Couldn't set up shared node_modules: $!" |
92
|
|
|
|
|
|
|
unless -e 'node_modules'; |
93
|
0
|
|
|
|
|
|
return $work_dir; |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
1; |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
=encoding utf8 |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
=head1 NAME |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
Mojo::Alien::npm - Runs the external nodejs program npm |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
=head1 SYNOPSIS |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
use Mojo::Alien::npm; |
107
|
|
|
|
|
|
|
my $npm = Mojo::Alien::npm->new; |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
$npm->init; |
110
|
|
|
|
|
|
|
$npm->install; |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
=head1 DESCRIPTION |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
L is a class for runnig the external nodejs program |
115
|
|
|
|
|
|
|
L. |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
=head1 ATTRIBUTES |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
=head2 binary |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
$array_ref = $npm->binary; |
122
|
|
|
|
|
|
|
$npm = $npm->binary(['npm']); |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
The path to the npm executable. Default is "npm" unless the C |
125
|
|
|
|
|
|
|
environment variable has been set. This can also be set to "pnpm" in case you |
126
|
|
|
|
|
|
|
prefer L. |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
=head2 config |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
$path = $npm->config; |
131
|
|
|
|
|
|
|
$npm = $npm->config(path->to_abs->child('package.json')); |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
Holds an I path to "package.json". |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
=head2 mode |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
$str = $npm->mode; |
138
|
|
|
|
|
|
|
$npm = $npm->mode('development'); |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
Should be either "development" or "production". Will be used as "NODE_ENV" |
141
|
|
|
|
|
|
|
environment variable when calling "npm". |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
=head1 METHODS |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
=head2 dependencies |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
$dependencies = $npm->dependencies; |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
Used to get dependencies from L combined with information from |
150
|
|
|
|
|
|
|
C. The returned hash-ref looks like this: |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
{ |
153
|
|
|
|
|
|
|
"package-name" => { |
154
|
|
|
|
|
|
|
required => $str, # version from package.json |
155
|
|
|
|
|
|
|
type => $str, # dev, optional or prod |
156
|
|
|
|
|
|
|
version => $str, # installed version |
157
|
|
|
|
|
|
|
... |
158
|
|
|
|
|
|
|
}, |
159
|
|
|
|
|
|
|
... |
160
|
|
|
|
|
|
|
} |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=head2 init |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
$npm->init; |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
Used to create a default L file. |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=head2 install |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
$npm->install; |
171
|
|
|
|
|
|
|
$npm->install('package-name'); |
172
|
|
|
|
|
|
|
$npm->install('package-name', {type => 'prod', version => '0.1.2'}); |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
Installs either all modules from L or a given package by name. An |
175
|
|
|
|
|
|
|
additional C<$info> hash can also be provided. |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
=head1 SEE ALSO |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
L. |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=cut |