squared 0.0.10 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,29 +4,38 @@ module Squared
4
4
  module Workspace
5
5
  module Project
6
6
  class Node < Git
7
+ include Common::Prompt
8
+
7
9
  class << self
8
10
  def populate(*); end
9
11
 
10
12
  def tasks
11
- nil
13
+ %i[outdated].freeze
14
+ end
15
+
16
+ def batchargs
17
+ [ref, { refresh: %i[build copy] }]
18
+ end
19
+
20
+ def aliasargs
21
+ [ref, { refresh: :build }]
12
22
  end
13
23
 
14
24
  def prod?
15
25
  ENV['NODE_ENV'] == 'production'
16
26
  end
17
27
 
18
- def is_a?(val)
19
- if (val = as_path(val))
20
- val.join('package.json').exist?
21
- else
22
- super
23
- end
28
+ def config?(val)
29
+ return false unless (val = as_path(val))
30
+
31
+ val.join('package.json').exist?
24
32
  end
25
33
  end
26
34
 
27
35
  @@tasks[ref] = {
28
- install: %i[force frozen dedupe],
29
- outdated: %i[major minor patch],
36
+ install: %i[force frozen dedupe].freeze,
37
+ outdated: %i[major minor patch].freeze,
38
+ bump: %i[major minor patch].freeze,
30
39
  run: nil
31
40
  }.freeze
32
41
 
@@ -58,11 +67,55 @@ module Squared
58
67
  if flags.nil?
59
68
  case action
60
69
  when :run
61
- desc format_desc(action, nil, 'command+')
70
+ desc format_desc(action, nil, 'command+|^index|#,pattern*')
62
71
  task action, [:command] do |_, args|
63
- cmd = args.to_a
64
- guard_params(action, 'command', args: cmd)
65
- cmd.each { |val| run_s compose(val) }
72
+ if args.command == '#'
73
+ list = read_scripts
74
+ grep = args.extras.map { |val| Regexp.new(val) }
75
+ lines = []
76
+ if (pad = list.size) > 0
77
+ pad = pad.to_s.size
78
+ list.each_with_index do |val, i|
79
+ next unless grep.empty? || grep.any? { |pat| pat.match?(val[0]) }
80
+
81
+ lines << "#{(i + 1).to_s.rjust(pad)}. #{val[0]}"
82
+ end
83
+ end
84
+ if lines.empty?
85
+ lines = ['No scripts were found:', '']
86
+ unless args.extras.empty?
87
+ i = 0
88
+ lines += args.extras.to_a.map { |s| "#{i += 1}. #{s}" }
89
+ lines << ''
90
+ end
91
+ lines << package.to_s
92
+ pat = /^(#{Regexp.escape(lines.last)})(.*)$/
93
+ else
94
+ pat = /^(\s*\d+\.)(.+)$/
95
+ end
96
+ emphasize(lines, title: task_join(name, 'run[^N]'), border: borderstyle, sub: [
97
+ headerstyle,
98
+ { pat: pat, styles: theme[:active] }
99
+ ])
100
+ else
101
+ cmd = args.to_a
102
+ guard_params(action, 'command', args: cmd)
103
+ list = nil
104
+ cmd.each do |val|
105
+ if (data = /\A\^(\d+)\z/.match(val))
106
+ list ||= read_scripts
107
+ n = data[1].to_i
108
+ if (item = list[n - 1])
109
+ val = item.first
110
+ elsif exception
111
+ raise_error("requested index #{n}", hint: "total #{list.size}")
112
+ else
113
+ next log.warn "run script #{n} of #{list.size} (out of range)"
114
+ end
115
+ end
116
+ run compose(val, script: true)
117
+ end
118
+ end
66
119
  end
67
120
  end
68
121
  else
@@ -75,10 +128,15 @@ module Squared
75
128
  depend(flag)
76
129
  end
77
130
  when :outdated
78
- desc format_desc(action, flag, %w[prune interactive dry-run], arg: 'opts?')
131
+ desc format_desc(action, flag, %w[prune interactive dry-run].freeze, arg: 'opts?')
79
132
  task flag, [:opts] do |_, args|
80
133
  outdated(flag, opts: args.to_a)
81
134
  end
135
+ else
136
+ desc format_desc(action, flag)
137
+ task flag do
138
+ __send__(action, flag)
139
+ end
82
140
  end
83
141
  end
84
142
  end
@@ -87,17 +145,17 @@ module Squared
87
145
  end
88
146
  end
89
147
 
90
- def copy(from: 'build', glob: '**/*', subdir: 'node_modules', into: nil, also: nil, override: false)
148
+ def copy(from: 'build', glob: '**/*', into: 'node_modules', scope: nil, also: nil, override: false)
91
149
  if @copy && !override
92
150
  return super if runnable?(@copy)
93
151
 
94
152
  from = @copy[:from] if @copy.key?(:from)
95
153
  glob = @copy[:glob] if @copy.key?(:glob)
96
- subdir = @copy[:subdir] if @copy.key?(:subdir)
97
154
  into = @copy[:into] if @copy.key?(:into)
155
+ scope = @copy[:scope] if @copy.key?(:scope)
98
156
  also = @copy[:also] if @copy.key?(:also)
99
157
  end
100
- items = [path == workspace.home ? nil : workspace.home]
158
+ items = [path != workspace.home && workspace.home? ? workspace.home : nil]
101
159
  items += as_a(also) if also
102
160
  items.each_with_index do |dir, i|
103
161
  if i == 0
@@ -113,7 +171,7 @@ module Squared
113
171
  when ::Hash
114
172
  glob = '**/*'
115
173
  dest = nil
116
- into = nil
174
+ scope = nil
117
175
  dir.each do |key, val|
118
176
  case key.to_sym
119
177
  when :target
@@ -122,8 +180,8 @@ module Squared
122
180
  from = val
123
181
  when :glob
124
182
  glob = val
125
- when :subdir
126
- subdir = val
183
+ when :scope
184
+ scope = val
127
185
  when :into
128
186
  into = val
129
187
  end
@@ -131,18 +189,17 @@ module Squared
131
189
  when Project::Base
132
190
  dest = dir.path
133
191
  end
134
- next unless into
135
192
  end
136
193
  next unless dest&.directory?
137
194
 
138
195
  from = base_path(from)
139
- dest = dest.join(subdir, into || project)
140
- log.warn "cp #{from.join(glob)} #{dest}"
196
+ dest = dest.join(into, scope || project)
197
+ (glob = as_a(glob)).each { |val| log.info "cp #{from.join(val)} #{dest}" }
141
198
  copy_d(from, dest, glob: glob, verbose: verbose)
142
199
  end
143
200
  end
144
201
 
145
- def depend(flag = nil)
202
+ def depend(flag = nil, sync: invoked_sync?('depend', flag))
146
203
  if @depend && !flag
147
204
  super
148
205
  elsif outdated?
@@ -165,7 +222,7 @@ module Squared
165
222
  '--frozen-lockfile'
166
223
  end
167
224
  cmd << '--production' if flag && prod?
168
- cmd << '--ignore-engines' unless env('YARN_IGNORE_ENGINES', equals: '0')
225
+ cmd << '--ignore-engines' unless option('ignore-engines', equals: '0')
169
226
  end
170
227
  elsif pnpm?
171
228
  cmd = session 'pnpm'
@@ -179,11 +236,11 @@ module Squared
179
236
  end
180
237
  end
181
238
  cmd << '--prod' if flag && prod?
182
- if (val = env('PNPM_PUBLIC_HOIST_PATTERN'))
239
+ if (val = option('public-hoist-pattern', ignore: false))
183
240
  split_escape(val).each { |opt| cmd << "--public-hoist-pattern=#{shell_escape(opt, quote: true)}" }
184
241
  end
185
242
  cmd << '--ignore-workspace' if env('NODE_WORKSPACES', equals: '0')
186
- append_nocolor
243
+ append_nocolor option('no-color')
187
244
  else
188
245
  cmd = session 'npm'
189
246
  if flag == :dedupe
@@ -197,17 +254,23 @@ module Squared
197
254
  end
198
255
  cmd << '--omit=dev' if flag && prod?
199
256
  cmd << '--workspaces=false' if env('NODE_WORKSPACES', equals: '0')
200
- cmd << '--package-lock=false' if env('NPM_PACKAGE_LOCK', equals: '0')
201
- append_nocolor
257
+ cmd << '--package-lock=false' if option('package-lock', equals: '0')
258
+ append_nocolor option('no-color')
202
259
  end
203
260
  append_loglevel
204
- run(sync: invoked_sync?('depend', flag))
261
+ run(sync: sync)
205
262
  end
206
263
  end
207
264
 
208
265
  def outdated(rev = nil, opts: [])
209
- dryrun = opts.include?('dry-run') || !env('NODE_DRY_RUN').nil?
210
- cmd = pnpm? && read_packagemanager(ver: '7.15') ? 'pnpm outdated' : 'npm outdated'
266
+ dryrun = opts.include?('dry-run')
267
+ if pnpm? && read_packagemanager(version: '7.15')
268
+ cmd = 'pnpm outdated'
269
+ dryrun ||= !option('dry-run', prefix: 'pnpm').nil?
270
+ else
271
+ cmd = 'npm outdated'
272
+ dryrun ||= !option('dry-run', prefix: 'npm').nil?
273
+ end
211
274
  log.info cmd
212
275
  banner = format_banner("#{cmd}#{dryrun ? ' --dry-run' : ''}", multiple: true)
213
276
  if invoked_sync?('outdated', rev)
@@ -226,7 +289,7 @@ module Squared
226
289
  unless data.empty?
227
290
  JSON.parse(data).each_pair do |key, val|
228
291
  val = val.find { |obj| obj['dependent'] == json['name'] } if val.is_a?(::Array)
229
- next unless val && (file = dep1[key] || dep2[key])
292
+ next unless val && (file = dep1[key] || dep2[key]) && file != '*'
230
293
 
231
294
  latest = val['latest']
232
295
  ch = file[0]
@@ -238,11 +301,11 @@ module Squared
238
301
  avail << [key, file, latest, true]
239
302
  next
240
303
  end
241
- want = rev == :major && latest.match(SEM_VER) && !Regexp.last_match(6) ? latest : val['wanted']
304
+ want = rev == :major && (ver = latest.match(SEM_VER)) && !ver[6] ? latest : val['wanted']
242
305
  next unless (val['current'] != want || file != want) && (want.match?(SEM_VER) || !file.match?(SEM_VER))
243
306
 
244
- f = semver(file.scan(SEM_VER)).first
245
- w = semver(want.scan(SEM_VER)).first
307
+ f = semver(semscan(file))
308
+ w = semver(semscan(want))
246
309
  a = f[0]
247
310
  b = f[2]
248
311
  c = w[0]
@@ -294,7 +357,7 @@ module Squared
294
357
  col2 = size_col.(found, 1) + 4
295
358
  found.each_with_index do |item, i|
296
359
  a, b, c, d, e = item
297
- if inter && (rev != :major || e || semmajor(item[5], item[6])) && !confirm_outdated(a, c, d)
360
+ if inter && (rev != :major || e || semmajor(item[5], item[6])) && !confirm_outdated(a, c, d, e)
298
361
  cur = -1
299
362
  else
300
363
  cur = modified
@@ -354,12 +417,14 @@ module Squared
354
417
  end
355
418
  end
356
419
 
357
- def compose(opts)
420
+ def compose(opts, flags = nil, script: false)
421
+ return unless opts && script
422
+
358
423
  ret = session (if yarn?
359
424
  'yarn'
360
425
  else
361
426
  pnpm? ? 'pnpm' : 'npm'
362
- end), 'run'
427
+ end), 'run', flags
363
428
  append_loglevel
364
429
  case opts
365
430
  when ::Enumerable
@@ -372,6 +437,57 @@ module Squared
372
437
  ret
373
438
  end
374
439
 
440
+ def bump(flag)
441
+ return unless (ver = version)
442
+
443
+ seg = semscan(ver)
444
+ case flag
445
+ when :major
446
+ if seg[0] != '0' || seg[2].nil?
447
+ seg[0] = seg[0].succ
448
+ else
449
+ seg[2] = seg[2].succ
450
+ end
451
+ when :minor
452
+ if seg[0] == '0'
453
+ seg[4] &&= seg[4].succ
454
+ else
455
+ seg[2] = seg[2].succ
456
+ end
457
+ when :patch
458
+ seg[4] &&= seg[4].succ
459
+ end
460
+ unless (out = seg.join) == ver
461
+ begin
462
+ doc = package.read
463
+ if doc.sub!(/"version"\s*:\s*"#{ver}"/, "\"version\": \"#{out}\"")
464
+ package.write(doc)
465
+ log.info "bump version #{ver} to #{out} (#{flag})"
466
+ if verbose
467
+ major = flag == :major
468
+ emphasize("version: #{out}", title: name, border: borderstyle, sub: [
469
+ headerstyle,
470
+ { pat: /^(version:)( )(\S+)(.*)$/, styles: color(major ? :green : :yellow), index: 3 },
471
+ { pat: /^(version:)(.*)$/, styles: theme[major ? :major : :active] }
472
+ ])
473
+ elsif stdin?
474
+ puts out
475
+ end
476
+ else
477
+ raise_error('not found', hint: 'version')
478
+ end
479
+ rescue StandardError => e
480
+ log.debug e
481
+ raise
482
+ end
483
+ end
484
+ end
485
+
486
+ def version
487
+ read_packagemanager
488
+ @pm[:version]
489
+ end
490
+
375
491
  def install_type(prog = nil)
376
492
  prog ||= yarn? ? :yarn : :pnpm
377
493
  key = :"#{prog}?"
@@ -379,6 +495,10 @@ module Squared
379
495
  @pm[prog] || 0
380
496
  end
381
497
 
498
+ def depend?
499
+ @depend != false && (!@depend.nil? || outdated?)
500
+ end
501
+
382
502
  def copy?
383
503
  super || @copy.is_a?(::Hash)
384
504
  end
@@ -388,8 +508,8 @@ module Squared
388
508
  end
389
509
 
390
510
  def yarn?
391
- (@pm[:yarn] ||= if base_path('yarn.lock').exist?
392
- if (rc = base_path('.yarnrc.yml')).exist?
511
+ (@pm[:yarn] ||= if base_path('yarn.lock', ascend: find_package).exist?
512
+ if (rc = base_path('.yarnrc.yml', ascend: find_package)).exist?
393
513
  begin
394
514
  require 'yaml'
395
515
  doc = YAML.load_file(rc)
@@ -408,10 +528,10 @@ module Squared
408
528
  end
409
529
 
410
530
  def pnpm?
411
- (@pm[:pnpm] ||= if base_path('pnpm-lock.yaml').exist?
531
+ (@pm[:pnpm] ||= if base_path('pnpm-lock.yaml', ascend: find_package).exist?
412
532
  begin
413
533
  require 'yaml'
414
- doc = YAML.load_file(base_path('node_modules/.modules.yaml'))
534
+ doc = YAML.load_file(base_path('node_modules/.modules.yaml', ascend: find_package))
415
535
  @pm[:_] = doc['packageManager']
416
536
  case doc['nodeLinker']
417
537
  when 'hoisted'
@@ -429,6 +549,15 @@ module Squared
429
549
  end) > 0
430
550
  end
431
551
 
552
+ def workspaces?
553
+ if pnpm?
554
+ base_path('pnpm-workspace.yaml').exist?
555
+ else
556
+ read_packagemanager
557
+ @pm[:workspaces].is_a?(::Array)
558
+ end
559
+ end
560
+
432
561
  def dev?
433
562
  !Node.prod? && super
434
563
  end
@@ -439,6 +568,36 @@ module Squared
439
568
 
440
569
  private
441
570
 
571
+ def read_packagemanager(version: nil)
572
+ if @pm[:_].nil?
573
+ doc = JSON.parse(package.read)
574
+ @pm[:_] = (val = doc['packageManager']) ? val[0..(val.index('+') || 0) - 1] : false
575
+ @pm[:scripts] = doc['scripts']
576
+ @pm[:version] = doc['version']
577
+ @pm[:workspaces] = doc['workspaces']
578
+ end
579
+ rescue StandardError => e
580
+ log.debug e if package.exist?
581
+ @pm[:_] = false
582
+ nil
583
+ else
584
+ return if !@pm[:_] || (version && @pm[:_][@pm[:_].index('@') + 1..-1] < version)
585
+
586
+ @pm[:_]
587
+ end
588
+
589
+ def read_install
590
+ return unless (ret = env('NODE_INSTALL'))
591
+
592
+ @pm[:_] ||= ret if ret.include?('@')
593
+ ret
594
+ end
595
+
596
+ def read_scripts
597
+ read_packagemanager
598
+ @pm[:scripts].is_a?(Hash) ? @pm[:scripts].to_a : []
599
+ end
600
+
442
601
  def append_loglevel
443
602
  level = env('NODE_LOGLEVEL')
444
603
  silent = !verbose || level == 'silent'
@@ -471,43 +630,31 @@ module Squared
471
630
  end
472
631
  end
473
632
 
474
- def confirm_outdated(pkg, ver, rev)
475
- rev = case rev
476
- when 1
477
- 'MAJOR'
478
- when 3
479
- 'MINOR'
480
- else
481
- 'PATCH'
482
- end
483
- a = sub_style(rev, styles: theme[:header])
633
+ def confirm_outdated(pkg, ver, rev, lock)
634
+ a = sub_style(case rev
635
+ when 1
636
+ 'MAJOR'
637
+ when 3
638
+ 'MINOR'
639
+ else
640
+ 'PATCH'
641
+ end, styles: theme[:header])
484
642
  b = sub_style("#{pkg} #{ver}", styles: theme[:inline])
485
- c, d = rev == 'MAJOR' ? ['y/N', 'N'] : ['Y/n', 'Y']
486
- confirm("Upgrade to #{a}? #{b} [#{c}] ", d, timeout: 60)
643
+ c, d = rev == 1 || lock ? ['y/N', 'N'] : ['Y/n', 'Y']
644
+ e = lock ? " #{sub_style('(locked)', styles: color(:red))}" : ''
645
+ confirm("Upgrade to #{a}? #{b}#{e} [#{c}] ", d, timeout: 60)
487
646
  end
488
647
 
489
- def read_packagemanager(ver: nil)
490
- if @pm[:_].nil?
491
- doc = JSON.parse(package.read)
492
- @pm[:_] = (val = doc['packageManager']) ? val[0..(val.index('+') || 0) - 1] : false
493
- end
494
- rescue StandardError => e
495
- log.warn e if package.exist?
496
- @pm[:_] = false
497
- nil
498
- else
499
- return unless @pm[:_]
500
-
501
- ver ? @pm[:_][@pm[:_].index('@') + 1..-1] >= ver : @pm[:_]
648
+ def find_package
649
+ 'package.json' if parent&.has?('outdated', Node.ref)
502
650
  end
503
651
 
504
- def read_install
505
- return unless (ret = env('NODE_INSTALL'))
506
-
507
- @pm[:_] ||= ret if ret.include?('@')
508
- ret
652
+ def headerstyle
653
+ { pat: /^(\S+)(\s+)$/, styles: theme[:header] }
509
654
  end
510
655
  end
656
+
657
+ Application.implement Node
511
658
  end
512
659
  end
513
660
  end
@@ -12,21 +12,21 @@ module Squared
12
12
 
13
13
  class << self
14
14
  def populate(*); end
15
+ def batchargs(*); end
16
+ def aliasargs(*); end
15
17
 
16
18
  def tasks
17
- nil
19
+ %i[outdated].freeze
18
20
  end
19
21
 
20
22
  def venv?
21
23
  Dir.exist?(ENV.fetch('VIRTUAL_ENV', ''))
22
24
  end
23
25
 
24
- def is_a?(val)
25
- if (val = as_path(val))
26
- REQUIREMENTS.any? { |file| val.join(file).exist? }
27
- else
28
- super
29
- end
26
+ def config?(val)
27
+ return false unless (val = as_path(val))
28
+
29
+ REQUIREMENTS.any? { |file| val.join(file).exist? }
30
30
  end
31
31
  end
32
32
 
@@ -46,7 +46,7 @@ module Squared
46
46
  end
47
47
 
48
48
  @@tasks[ref] = {
49
- install: %i[user target upgrade force]
49
+ install: %i[user target upgrade force].freeze
50
50
  }.freeze
51
51
 
52
52
  def ref
@@ -74,7 +74,8 @@ module Squared
74
74
  else
75
75
  OPT_USER
76
76
  end
77
- desc format_desc(action, flag, list + OPT_GENERAL, req: req)
77
+ list += OPT_GENERAL
78
+ desc format_desc(action, flag, list, req: req)
78
79
  if flag == :target
79
80
  task flag, [:dir, :opts] do |_, args|
80
81
  guard_params(action, flag, args: args, key: :dir)
@@ -92,11 +93,10 @@ module Squared
92
93
  end
93
94
  end
94
95
 
95
- def depend(flag = nil, dir: nil, opts: [])
96
+ def depend(flag = nil, dir: nil, opts: [], sync: invoked_sync?('depend', flag))
96
97
  if @depend && !flag
97
98
  super
98
99
  elsif outdated?
99
- sync = invoked_sync?('depend', flag)
100
100
  case (type = install_type)
101
101
  when 1, 2
102
102
  cmd = pip_session 'install'
@@ -148,6 +148,10 @@ module Squared
148
148
  end
149
149
  end
150
150
 
151
+ def depend?
152
+ @depend != false && (!@depend.nil? || outdated?)
153
+ end
154
+
151
155
  def outdated?
152
156
  install_type > 0
153
157
  end
@@ -169,21 +173,23 @@ module Squared
169
173
  (v ? "-#{v[0]}" : "--#{opt}")
170
174
  end
171
175
  end
172
- @session << '--user' if env('PIP_USER')
173
- @session << '--no-input' if env('PIP_NO_INPUT')
174
- if (val = env('PIP_PROXY'))
176
+ @session << '--user' if option('user')
177
+ @session << '--no-input' if option('no-input')
178
+ if (val = option('proxy', ignore: false))
175
179
  @session << "--proxy=#{shell_escape(val, quote: true)}"
176
180
  end
177
- if (val = env('PIP_LOG'))
181
+ if (val = option('log', ignore: false))
178
182
  @session << "--log=#{shell_escape(base_path(val).to_s, quote: true)}"
179
183
  end
180
- append_nocolor
184
+ append_nocolor option('no-color')
181
185
  end
182
186
 
183
187
  def append_eager(opts)
184
188
  @session << '--upgrade-strategy=eager' if opts.include?('eager')
185
189
  end
186
190
  end
191
+
192
+ Application.implement Python
187
193
  end
188
194
  end
189
195
  end