squared 0.6.1 → 0.6.3

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.
@@ -6,20 +6,22 @@ module Squared
6
6
  class Node < Git
7
7
  OPT_NPM = {
8
8
  common: %w[dry-run=!? loglevel=b include-workspace-root=!? workspaces=!? w|workspace=v].freeze,
9
- install: %w[package-lock-only=!? prefer-dedupe=!? cpu=b libc=b os=b].freeze,
10
- install_a: %w[audit=! bin-links=! fund=! ignore-scripts=!? install-links=!? package-lock=! strict-peer-deps=!?
11
- include=b install-strategy=b omit=b].freeze,
12
- install_b: %w[no-save save-bundle save-dev save-optional save-peer save-prod before=q foreground-scripts=!?
13
- g|global=!? S|save=!? E|save-exact=!?].freeze,
9
+ install: %w[package-lock-only=!? prefer-dedupe=!? E|save-exact=!? before=q cpu=b libc=b os=b].freeze,
10
+ install_a: %w[audit=! bin-links=! foreground-scripts=!? fund=! ignore-scripts=!? install-links=!?
11
+ package-lock=! strict-peer-deps=!? include=b install-strategy=b omit=b].freeze,
12
+ install_b: %w[no-save B|save-bundle D|save-dev O|save-optional save-peer P|save-prod g|global=!?
13
+ S|save=!?].freeze,
14
14
  run: %w[foreground-scripts=!? if-present=!? ignore-scripts=!? script-shell=p].freeze,
15
15
  exec: %w[c|call=q package=b].freeze,
16
16
  pack: %w[ignore-scripts=!? json=!? pack-destination=p].freeze,
17
+ rebuild: %w[bin-links=! foreground-scripts=!? global=!? ignore-scripts=!? install-links=!?].freeze,
17
18
  no: {
18
19
  install: %w[audit bin-links fund package-lock].freeze
19
20
  }.freeze
20
21
  }.freeze
21
22
  OPT_PNPM = {
22
- common: %w[aggregate-output color no-color stream use-stderr C|dir=p loglevel=b w|workspace-root].freeze,
23
+ common: %w[aggregate-output color ignore-workspace-root-check no-color stream use-stderr C|dir=p loglevel=b
24
+ r|recursive w|workspace-root].freeze,
23
25
  common_cpu: %w[cpu=b libc=b os=b].freeze,
24
26
  common_filter: %w[fail-if-no-match changed-files-ignore-pattern=q filter=q filter-prod=q
25
27
  test-pattern=q].freeze,
@@ -30,15 +32,18 @@ module Squared
30
32
  modules-dir=p network-concurrency=i package-import-method=b public-hoist-pattern=q
31
33
  reporter=b].freeze,
32
34
  install_a: %w[global-dir ignore-scripts offline prefer-offline store-dir=p virtual-store-dir=p].freeze,
33
- install_b: %w[D|dev global-dir no-optional P|prod r|recursive].freeze,
35
+ install_b: %w[D|dev no-optional P|prod].freeze,
36
+ add: %w[allow-build config g|global save-catalog D|save-dev O|save-optional save-peer P|save-prod
37
+ save-catalog-name=b].freeze,
34
38
  update: %w[g|global i|interactive L|latest depth=i].freeze,
35
39
  dedupe: %w[check].freeze,
36
- run: %w[if-present no-bail parallel r|recursive report-summary reporter-hide-prefix resume-from
37
- sequential].freeze,
38
- exec: %w[no-reporter-hide-prefix parallel r|recursive report-summary resume-from c|shell-mode].freeze,
39
- pack: %w[json r|recursive pack-destination=p pack-gzip-level=i out=p workspace-concurrency=i].freeze,
40
+ run: %w[if-present no-bail parallel report-summary reporter-hide-prefix resume-from sequential].freeze,
41
+ exec: %w[no-reporter-hide-prefix parallel report-summary resume-from c|shell-mode].freeze,
42
+ pack: %w[json pack-destination=p pack-gzip-level=i out=p workspace-concurrency=i].freeze,
43
+ rebuild: %w[filter=q].freeze,
40
44
  no: {
41
- install: %w[frozen-lockfile verify-store-integrity].freeze
45
+ install: %w[frozen-lockfile verify-store-integrity].freeze,
46
+ add: %w[save-exact save-workspace-protocol].freeze
42
47
  }.freeze
43
48
  }.freeze
44
49
  OPT_YARN = {
@@ -50,13 +55,16 @@ module Squared
50
55
  network-timeout=i preferred-cache-folder=p production=b? proxy=q otp=b registry=q update-checksums
51
56
  use-yarnrc=p].freeze,
52
57
  install: %w[A|audit g|global S|save D|save-dev E|save-exact P|save-peer O|save-optional T|save-tilde].freeze,
58
+ add: %w[A|audit D|dev E|exact O|optional P|peer T|tilde ignore-workspace-root-check].freeze,
53
59
  update: %w[A|audit C|caret E|exact L|latest T|tilde P|pattern=q S|scope=b].freeze,
54
60
  run: %w[scripts-prepend-node-path=b?].freeze
55
61
  }.freeze
56
62
  OPT_BERRY = {
57
63
  install: %w[check-cache check-resolutions immutable immutable-cache inline-builds json refresh-lockfile
58
64
  mode=b].freeze,
59
- update: %w[C|caret E|exact F|fixed interactive T|tilde R|recursive mode=b].freeze,
65
+ add: %w[cached D|dev json O|optional P|peer prefer-dev].freeze,
66
+ add_a: %w[C|caret E|exact F|fixed interactive T|tilde mode=b].freeze,
67
+ update: %w[R|recursive].freeze,
60
68
  dedupe: %w[check json mode=b strategy=b].freeze,
61
69
  run: %w[B|binaries-only inspect inspect-brk T|top-level require=q].freeze,
62
70
  pack: %w[n|dry-run install-if-needed json o|out=p].freeze
@@ -128,7 +136,7 @@ module Squared
128
136
  end
129
137
 
130
138
  subtasks({
131
- 'package' => %i[install reinstall dedupe update].freeze,
139
+ 'package' => %i[install add update dedupe rebuild reinstall].freeze,
132
140
  'outdated' => %i[major minor patch].freeze,
133
141
  'bump' => %i[version major minor patch].freeze,
134
142
  'publish' => %i[latest tag].freeze,
@@ -170,18 +178,17 @@ module Squared
170
178
  if flags.nil?
171
179
  case action
172
180
  when 'add'
173
- format_desc action, nil, 'save?=prod|dev|optional|peer,name+'
181
+ format_desc action, nil, 'save?=[=-]prod|dev|optional|peer|bundle,(-)name+'
174
182
  task action, [:save] do |_, args|
175
- packages = if args.save =~ /\A(=)?(prod|dev|optional|peer)\z/
176
- exact = !$1.nil?
177
- save = $2
183
+ packages = if args.save =~ /\A([=-]*)?(prod|dev|optional|peer|bundle)\z/
184
+ save = [$2, $1.include?('='), $1.include?('-')]
178
185
  args.extras
179
186
  else
180
187
  save = 'prod'
181
188
  args.to_a
182
189
  end
183
190
  param_guard(action, 'name', args: packages)
184
- depend(:add, packages: packages, save: save, exact: exact)
191
+ depend(:add, packages: packages, save: save)
185
192
  end
186
193
  when 'run'
187
194
  next if scripts.empty?
@@ -279,7 +286,7 @@ module Squared
279
286
  end
280
287
  when 'package'
281
288
  format_desc(action, flag, 'opts*', before: case flag
282
- when :dedupe then nil
289
+ when :dedupe, :rebuild then nil
283
290
  when :reinstall then 'force?'
284
291
  else 'name*'
285
292
  end)
@@ -302,22 +309,21 @@ module Squared
302
309
  end
303
310
  end
304
311
  when 'publish'
305
- format_desc(action, flag, 'otp?,d/ry-run?,p/ublic|r/estricted?',
306
- before: ('tag' if flag == :tag))
312
+ format_desc(action, flag, 'otp?,p/ublic|r/estricted?,d/ry-run?', before: ('tag' if flag == :tag))
307
313
  task flag do |_, args|
308
314
  args = args.to_a
309
- dryrun = true if args.delete('dry-run') || args.delete('d')
310
- access = if args.delete('public') || args.delete('p')
311
- 'public'
312
- elsif args.delete('restricted') || args.delete('r')
315
+ access = if has_value!(args, 'r', 'restricted')
313
316
  'restricted'
317
+ elsif has_value!(args, 'p', 'public')
318
+ 'public'
314
319
  end
320
+ dryrun = has_value!(args, 'd', 'dry-run')
315
321
  if flag == :latest
316
322
  otp = args.first
317
323
  else
318
324
  tag, otp = param_guard(action, flag, args: args)
319
325
  end
320
- publish(flag, otp: otp, tag: tag, dryrun: dryrun, access: access)
326
+ publish(flag, otp: otp, tag: tag, access: access, dryrun: dryrun)
321
327
  end
322
328
  when 'tsc'
323
329
  break unless @tsfile
@@ -325,15 +331,11 @@ module Squared
325
331
  format_desc(action, flag, 'opts*', "#{flag == :project ? 'before' : 'after'}": 'config?')
326
332
  task flag do |_, args|
327
333
  args = args.to_a
328
- if flag == :project
329
- project = if !args.empty? && exist?(args.first)
330
- args.shift
331
- else
332
- @tsfile
333
- end
334
- end
335
- watch = !(args.delete('watch') || args.delete('w')).nil?
336
- tsc(*args, banner: true, project: project, build: flag == :build, watch: watch)
334
+ tsc(*args, banner: true, "#{flag}": if flag == :build
335
+ true
336
+ else
337
+ exist?(args.first) ? args.shift : @tsfile
338
+ end, watch: has_value!(args, 'w', 'watch'))
337
339
  end
338
340
  end
339
341
  end
@@ -345,6 +347,8 @@ module Squared
345
347
 
346
348
  def copy(from: 'build', into: 'node_modules', scope: nil, also: nil, create: nil, files: nil, workspace: false,
347
349
  link: false, force: false, override: false, sync: invoked_sync?('copy'), **kwargs)
350
+ return if @copy == false
351
+
348
352
  glob = kwargs[:include]
349
353
  pass = kwargs[:exclude]
350
354
  if @copy && !override
@@ -361,8 +365,6 @@ module Squared
361
365
  create = @copy[:create] if @copy.key?(:create)
362
366
  glob = @copy[:include] if @copy.key?(:include)
363
367
  pass = @copy[:exclude] if @copy.key?(:exclude)
364
- elsif @copy == false
365
- return
366
368
  end
367
369
  items = []
368
370
  if build? && path != @workspace.home && @workspace.home?
@@ -373,7 +375,7 @@ module Squared
373
375
  return if items.empty?
374
376
 
375
377
  on :first, :copy
376
- print_item unless @output[0] || !verbose || task_invoked?(/^copy(?::#{Node.ref}|$)/)
378
+ print_item unless @output[0] || silent? || task_invoked?(/^copy(?::#{Node.ref}|$)/)
377
379
  packed = false
378
380
  items.each do |dir|
379
381
  case dir
@@ -381,7 +383,7 @@ module Squared
381
383
  dest = dir
382
384
  @workspace.rev_clear(dest, sync: sync)
383
385
  when String
384
- dest = @workspace.root + dir
386
+ dest = @workspace.rootpath(dir)
385
387
  @workspace.rev_clear(dest, sync: sync)
386
388
  when Symbol
387
389
  dest = if (proj = @workspace.find(name: dir))
@@ -422,8 +424,7 @@ module Squared
422
424
  .scan(/^npm notice \d+(?:\.\d+)?[a-z]+ (.+)$/i)
423
425
  .map { |item| Pathname.new(item.first) }
424
426
  .select(&:exist?)
425
- end
426
- .concat(Array(files))
427
+ end.concat(Array(files))
427
428
  packed = true
428
429
  end
429
430
  base = dest.join(into, npmname)
@@ -438,7 +439,7 @@ module Squared
438
439
  target.mkpath
439
440
  subdir << target.to_s
440
441
  end
441
- FileUtils.cp(basepath(s), dest, verbose: verbosetype > 0)
442
+ FileUtils.cp(basepath(s), dest, verbose: !silent?)
442
443
  rescue StandardError => e
443
444
  print_error e
444
445
  errors += 1
@@ -446,7 +447,7 @@ module Squared
446
447
  rescue StandardError => e
447
448
  on_error e, :copy
448
449
  else
449
- puts message(base, subdir.size, files.size - errors) if verbose
450
+ puts message(base, subdir.size, files.size - errors) unless silent?
450
451
  end
451
452
  next
452
453
  end
@@ -479,7 +480,7 @@ module Squared
479
480
  end
480
481
  target.each do |src, to|
481
482
  glob.each { |val| log.info "cp #{from + val} #{to}" }
482
- copy_dir(src, to, glob, create: create, link: link, force: force, pass: pass, verbose: verbosetype > 0)
483
+ copy_dir(src, to, glob, create: create, link: link, force: force, pass: pass, verbose: !silent?)
483
484
  rescue StandardError => e
484
485
  on_error e, :copy
485
486
  end
@@ -487,45 +488,81 @@ module Squared
487
488
  on :last, :copy
488
489
  end
489
490
 
490
- def depend(flag = nil, *, sync: invoked_sync?('depend', flag), packages: [], save: nil, exact: nil, **)
491
+ def depend(flag = nil, *, sync: invoked_sync?('depend', flag), packages: [], save: nil, exact: nil,
492
+ omit: env('NPM_OMIT'), **)
491
493
  if @depend && !flag
492
494
  super
493
495
  elsif outdated?
494
496
  workspace.rev_clear(name, sync: sync)
495
497
  return update if !flag && env('NODE_UPDATE')
496
498
 
499
+ add = flag == :add
500
+ if add
501
+ remove, packages = packages.partition { |val| val.delete_prefix!('-') }
502
+ remove.map! { |pkg| shell_quote(pkg) }
503
+ end
504
+ save, exact, omit = save if save.is_a?(Array)
497
505
  ws = env('NODE_WORKSPACES', equals: '0')
498
- ci = option('ci')
506
+ ci = -> { option('ci') }
507
+ is = -> { option('ignore-scripts') }
508
+ om = lambda do
509
+ next unless omit
510
+
511
+ save = case save
512
+ when 'peer'
513
+ 'optional'
514
+ when 'optional'
515
+ 'dev'
516
+ when 'dev'
517
+ 'prod'
518
+ end
519
+ end
520
+ rm = lambda do |target|
521
+ next if remove.empty?
522
+
523
+ run(target.temp(*remove).sub!(/ (?:add|install) /, ' remove '), from: :remove, sync: sync)
524
+ end
499
525
  if (yarn = dependtype(:yarn)) > 0
500
- cmd = session 'yarn'
501
- if flag == :add
502
- cmd << 'add'
503
- cmd << "--#{save}" unless save == 'prod'
504
- cmd << '--exact' if exact
526
+ cmd = session('yarn', flag || 'install')
527
+ append_loglevel
528
+ if yarn == 1
529
+ cmd << '--ignore-engines' unless option('ignore-engines', equals: '0')
530
+ cmd << '--ignore-scripts' if is.call
531
+ cmd << '--force' if option('force')
505
532
  else
506
- cmd << 'install'
507
- cmd << '--ignore-engines' if yarn == 1 && !option('ignore-engines', equals: '0')
508
- cmd << (yarn == 1 ? '--force' : '--check-cache') if option('force')
533
+ cmd << '--mode=skip-build' if is.call
534
+ cmd << '--check-cache' if !flag && option('force')
509
535
  end
510
536
  if nolockfile?('yarn')
511
537
  cmd << '--no-lockfile'
512
- elsif ci
538
+ elsif ci.call
513
539
  if yarn == 1
514
540
  cmd << '--frozen-lockfile'
515
- else
541
+ elsif !flag
516
542
  cmd << '--immutable' << '--refresh-lockfile'
517
543
  end
518
544
  end
545
+ if add
546
+ cmd << '-W' if yarn == 1 && !option('w', 'ignore-workspace-root-check', equals: '0')
547
+ rm.call(cmd)
548
+ om.call
549
+ cmd << "--#{save}" if save && save != 'bundle'
550
+ cmd << '--exact' if exact
551
+ end
519
552
  elsif pnpm?
520
- cmd = session 'pnpm'
521
- if flag == :add
522
- cmd << 'add' << "--save-#{save}"
553
+ cmd = session('pnpm', flag || 'install')
554
+ append_nocolor
555
+ append_loglevel
556
+ if add
557
+ om.call
558
+ cmd << "--save-#{save}" if save && save != 'bundle'
559
+ rm.call(cmd)
523
560
  cmd << '--save-exact' if exact
561
+ option('allow-build') { |val| cmd << quote_option('allow-build', val) }
524
562
  else
525
- cmd << 'install'
526
563
  append_platform
527
564
  end
528
- option('public-hoist-pattern', ignore: false) do |val|
565
+ option('public-hoist-pattern') do |val|
529
566
  split_escape(val) { |opt| cmd << shell_option('public-hoist-pattern', opt) }
530
567
  end
531
568
  cmd << '--ignore-workspace' if ws
@@ -533,30 +570,37 @@ module Squared
533
570
  '--force'
534
571
  elsif nolockfile?('pnpm')
535
572
  '--no-lockfile'
536
- elsif ci
573
+ elsif ci.call
537
574
  '--frozen-lockfile'
538
575
  end
539
- append_nocolor
576
+ cmd << '--ignore-scripts' if is.call
540
577
  else
541
- cmd = session 'npm'
542
- if ci
543
- cmd << 'ci'
544
- else
545
- cmd << 'install'
546
- if flag == :add
547
- cmd << "--save-#{save}"
578
+ cmd = session('npm', (ci = ci.call) ? 'ci' : 'install')
579
+ cmd << '--workspaces=false' if ws
580
+ append_nocolor
581
+ append_loglevel
582
+ if omit
583
+ cmd << "--omit=#{save}"
584
+ save = nil
585
+ end
586
+ unless ci
587
+ if add
588
+ cmd << "--save-#{save}" if save
589
+ rm.call(cmd)
548
590
  cmd << '--save-exact' if exact
549
- cmd.merge(packages.map { |pkg| shell_quote(pkg) })
550
591
  else
551
592
  append_platform
552
593
  end
553
594
  end
554
- cmd << '--workspaces=false' if ws
555
595
  cmd << '--package-lock=false' << 'save=false' if nolockfile?('npm')
556
- append_nocolor
596
+ cmd << '--ignore-scripts' if is.call
557
597
  end
558
- append_loglevel
559
- run(from: :depend, sync: sync)
598
+ if add
599
+ return if packages.empty?
600
+
601
+ cmd.merge(packages.map { |pkg| shell_quote(pkg) })
602
+ end
603
+ run(from: flag || :depend, sync: sync)
560
604
  end
561
605
  end
562
606
 
@@ -652,11 +696,8 @@ module Squared
652
696
  end
653
697
  pending = 0
654
698
  modified = 0
655
- size_col = ->(a, i) { a.map { |aa| aa[i] }.max_by(&:size).size }
656
- pad_ord = lambda do |val, ord|
657
- ret = val.succ.to_s
658
- ord.size > 9 ? ret.rjust(ord.size.to_s.size) : ret
659
- end
699
+ width = ->(a, i) { a.map { |aa| aa[i] }.max_by(&:size).size }
700
+ pad = ->(val, ord) { val.succ.to_s.rjust([ord.size.to_s.size, 2].max) }
660
701
  footer = lambda do |val, size|
661
702
  next unless verbose
662
703
 
@@ -670,19 +711,21 @@ module Squared
670
711
  end
671
712
  print_item banner unless sync
672
713
  if !found.empty?
673
- col1 = size_col.call(found, 0) + 4
674
- col2 = size_col.call(found, 1) + 4
714
+ col1 = width.call(found, 0) + 4
715
+ col2 = width.call(found, 1) + 4
675
716
  packages = []
676
- pat = ->(a) { /("#{Regexp.escape(a[0])}"\s*:\s*)"([~^])#{a[4] ? '?' : ''}#{Regexp.escape(a[1])}"/ }
717
+ pat = ->(a) { /("#{Regexp.escape(a[0])}"\s*:\s*)"([~^])#{'?' if a[4]}#{Regexp.escape(a[1])}"/ }
677
718
  edit = lambda do |a, pkg, mod|
678
719
  packages << a[0]
679
720
  modified += 1
680
721
  "#{pkg}\"#{mod || (a[3] == 1 && a[4] ? '^' : '')}#{a[2]}\""
681
722
  end
723
+ kwargs = { col1: col1, col2: col2, col3: width.call(found, 2), timeout: 0 }
682
724
  found.each_with_index do |item, i|
683
725
  a, b, c, d, e = item
684
726
  f = ia && (rev != :major || e || semmajor?(item[5], item[6]))
685
- if f && !confirm_outdated(a, c, (d / 2.0).ceil, b, lock: e, col1: col1, timeout: 0)
727
+ col0 = "#{pad.call(i, found)}. "
728
+ if f && !confirm_outdated(a, c, (d / 2.0).ceil, b, lock: e, col0: col0, **kwargs)
686
729
  cur = -1
687
730
  else
688
731
  cur = modified
@@ -696,9 +739,14 @@ module Squared
696
739
  end
697
740
  end
698
741
  end
699
- a = a.ljust(col1)
700
- b = b.ljust(col2)
701
- b = sub_style(b, styles: theme[:current]) if theme[:current] && !stdin?
742
+ if f
743
+ a = ' ' * col1
744
+ b = ' ' * col2
745
+ else
746
+ a = a.ljust(col1)
747
+ b = b.ljust(col2)
748
+ sub_style! b, theme[:current] if theme[:current] && !stdin?
749
+ end
702
750
  c = if cur == -1
703
751
  'SKIP'
704
752
  elsif modified == cur
@@ -708,15 +756,15 @@ module Squared
708
756
  else
709
757
  g = item
710
758
  if d == 1
711
- a = sub_style(a, styles: theme[:major])
712
- sub_style(c, :bold, styles: color(:green))
759
+ sub_style! a, theme[:major]
760
+ sub_style c, :bold, color(:green)
713
761
  else
714
762
  sub_style(c, **opt_style(color(d == 3 ? :green : :yellow), SEM_VER, d))
715
763
  end
716
764
  end
717
765
  s = a + b + c
718
766
  if !items
719
- puts "#{pad_ord.call(i, found)}. #{s}"
767
+ puts "#{f ? ' ' * col0.size : col0}#{s}"
720
768
  elsif g
721
769
  items << [s, g]
722
770
  end
@@ -754,20 +802,20 @@ module Squared
754
802
  end
755
803
  end
756
804
  elsif !avail.empty?
757
- col1 = size_col.call(avail, 0) + 4
758
- col2 = size_col.call(avail, 1)
759
- col3 = size_col.call(avail, 2) + 4
805
+ col1 = width.call(avail, 0) + 4
806
+ col2 = width.call(avail, 1)
807
+ col3 = width.call(avail, 2) + 4
760
808
  avail.each_with_index do |item, i|
761
809
  a, b, c, d = item
762
810
  a = a.ljust(col1)
763
- b = sub_style(b.ljust(col2), styles: color(d ? :red : :yellow))
811
+ b = sub_style b.ljust(col2), color(d ? :red : :yellow)
764
812
  c = c.ljust(col3)
765
813
  unless d
766
- a = sub_style(a, styles: theme[:active])
767
- c = sub_style(c, styles: color(:green))
814
+ sub_style! a, theme[:active]
815
+ sub_style! c, color(:green)
768
816
  pending += 1
769
817
  end
770
- puts "#{pad_ord.call(i, avail)}. #{(a + c + b).subhint(d ? 'locked' : 'latest')}"
818
+ puts "#{pad.call(i, avail)}. #{(a + c + b).subhint(d ? 'locked' : 'latest')}"
771
819
  end
772
820
  footer.call(0, avail.size)
773
821
  else
@@ -782,7 +830,7 @@ module Squared
782
830
 
783
831
  def publish(flag = nil, *, sync: invoked_sync?('publish', flag), otp: nil, tag: nil, access: nil, dryrun: nil)
784
832
  if read_package('private')
785
- ws = @children.select { |proj| proj.ref?(Node.ref) }
833
+ ws = children.select { |proj| proj.ref?(Node.ref) }
786
834
  if ws.empty?
787
835
  print_error('nothing to publish', subject: name, hint: 'private')
788
836
  elsif confirm_basic('Publish workspace?', ws.map(&:name).join(', '), 'N')
@@ -825,10 +873,16 @@ module Squared
825
873
 
826
874
  def package(flag, opts = [], packages: [], from: nil)
827
875
  workspace.rev_clear(name)
828
- if (yarn = dependtype(:yarn)) > 0
876
+ yarn = dependtype(:yarn)
877
+ if yarn > 0 && !(yarn == 1 && ((flag == :update && !packages.empty?) || flag == :rebuild))
829
878
  cmd = session 'yarn', case flag
830
879
  when :update
831
- yarn == 1 ? 'upgrade' : 'up'
880
+ if yarn == 1
881
+ 'upgrade'
882
+ else
883
+ spec = 0
884
+ 'up'
885
+ end
832
886
  when :reinstall
833
887
  if yarn == 1
834
888
  remove_modules 'yarn' if opts.include?('force')
@@ -837,35 +891,51 @@ module Squared
837
891
  end
838
892
  opts << 'no-lockfile' if lockfile(true)
839
893
  'install'
894
+ when :add
895
+ spec = 1
896
+ 'add'
840
897
  else
841
898
  yarn == 1 && flag == :dedupe ? 'install' : flag
842
899
  end
843
900
  op = OptionPartition.new(opts, if yarn == 1
844
901
  OPT_YARN.fetch(flag == :dedupe ? :install : flag, []) + OPT_YARN[:common]
845
902
  else
846
- OPT_BERRY.fetch(flag, [])
903
+ OPT_BERRY.fetch(flag, []) + case flag
904
+ when :add, :update then OPT_BERRY[:add_a]
905
+ else []
906
+ end
847
907
  end, cmd, project: self)
848
908
  if yarn == 1 && flag != :reinstall
849
909
  op << '--no-lockfile' if nolockfile?('yarn')
850
910
  op << '--ignore-engines' unless option('ignore-engines', equals: '0')
851
911
  end
852
- op.clear
853
- append_loglevel
854
912
  else
855
913
  args = if pnpm?
856
914
  case flag
857
915
  when :install, :update
858
916
  opts << 'no-lockfile' if nolockfile?('pnpm')
917
+ spec = 0 if flag == :update
918
+ when :add
919
+ spec = 1
859
920
  when :reinstall
860
921
  opts << 'force'
861
922
  flag = :install
862
923
  end
863
- no = OPT_PNPM[:no][flag]
924
+ flags = [flag]
925
+ unless flag == :rebuild
926
+ flags << :install_a
927
+ no = OPT_PNPM[:no][flag]
928
+ end
864
929
  [
865
930
  opts,
866
- [flag, :install_a].yield_self do |out|
867
- out.push(:install_b, :common_filter) unless flag == :dedupe
868
- out << :common_cpu unless flag == :update
931
+ flags.yield_self do |out|
932
+ unless flag == :dedupe
933
+ out << :common_filter
934
+ unless flag == :add
935
+ out << :install_b
936
+ out << :common_cpu unless flag == :update
937
+ end
938
+ end
869
939
  pnpmopts(*out)
870
940
  end,
871
941
  session('pnpm', flag)
@@ -874,27 +944,51 @@ module Squared
874
944
  case flag
875
945
  when :install, :update
876
946
  opts.unshift('package-lock=false', 'save=false') if nolockfile?('npm')
947
+ spec = 0
948
+ when :add
949
+ spec = 1
950
+ flag = :install
877
951
  when :reinstall
878
952
  remove_modules 'npm' if opts.delete('force')
879
953
  opts.unshift('package-lock=false') if lockfile(true)
880
954
  flag = :install
881
955
  end
882
- no = OPT_NPM[:no][:install]
956
+ flags = [flag]
957
+ unless flag == :rebuild
958
+ flags << :install_a
959
+ unless flag == :dedupe
960
+ %w[save ignore-scripts strict-peer-deps].each do |key|
961
+ option(key, prefix: 'npm', ignore: false) do |val|
962
+ opts << case val
963
+ when '0', 'false'
964
+ "#{key}=false"
965
+ else
966
+ "#{key}=true"
967
+ end
968
+ end
969
+ end
970
+ flags << :install_b
971
+ end
972
+ no = OPT_NPM[:no][:install]
973
+ end
883
974
  [
884
975
  opts,
885
- [flag, :install_a].yield_self do |out|
886
- out << :install_b unless flag == :dedupe
887
- npmopts(*out)
888
- end,
976
+ npmopts(*flags),
889
977
  session('npm', flag)
890
978
  ]
891
979
  end
892
980
  op = OptionPartition.new(*args, no: no, project: self)
981
+ append_platform if flag == :install
982
+ append_nocolor
983
+ end
984
+ append_loglevel
985
+ case spec
986
+ when 0, 1
893
987
  op.each do |opt|
894
988
  if opt =~ op.values
895
989
  case $1
896
990
  when 'w', 'workspace'
897
- op << ($2.match?(%r{[\\/]}) ? quote_option($1, basepath($2)) : shell_option($1, $2))
991
+ op << quotepath($1, $2)
898
992
  end
899
993
  elsif opt.include?('=') || opt.start_with?('-')
900
994
  op.errors << opt
@@ -904,26 +998,18 @@ module Squared
904
998
  end
905
999
  op.swap
906
1000
  .concat(packages)
907
- append_platform if flag == :install
908
- append_nocolor
909
- append_loglevel
910
- if flag == :dedupe
911
- op.clear
912
- else
913
- op.append(quote: true)
914
- end
915
- op.clear(errors: true)
1001
+ raise_error ArgumentError, 'no packages to add' if op.empty? && spec == 1
1002
+ op.append(quote: true)
1003
+ .clear(errors: true)
1004
+ else
1005
+ op.clear
916
1006
  end
917
1007
  run(from: from || :"package:#{flag}")
918
1008
  end
919
1009
 
920
1010
  def bump(flag, val = nil)
921
- if flag != :version
922
- val = sembump version, flag
923
- return if val == version
924
- elsif !val
925
- return
926
- end
1011
+ return unless val ||= sembump(version, flag)
1012
+
927
1013
  doc = dependfile.read
928
1014
  if doc.sub!(/"version"\s*:\s*"#{version}"/, "\"version\": \"#{val}\"")
929
1015
  unless dryrun?
@@ -933,7 +1019,7 @@ module Squared
933
1019
  end
934
1020
  if stdin?
935
1021
  puts val
936
- elsif verbose
1022
+ elsif !silent?
937
1023
  major = flag == :major
938
1024
  emphasize("version: #{val}", title: name, border: borderstyle, sub: [
939
1025
  headerstyle,
@@ -967,7 +1053,7 @@ module Squared
967
1053
 
968
1054
  case $1
969
1055
  when 'w', 'workspace'
970
- op << ($2.match?(%r{[\\/]}) ? quote_option($1, basepath($2)) : shell_option($1, $2))
1056
+ op << quotepath($1, $2)
971
1057
  op.found << opt
972
1058
  end
973
1059
  end
@@ -1239,7 +1325,7 @@ module Squared
1239
1325
 
1240
1326
  def append_loglevel(target: @session)
1241
1327
  level = env('NODE_LOGLEVEL')
1242
- silent = !verbose || level == 'silent'
1328
+ silent = silent? || level == 'silent'
1243
1329
  return unless silent || level
1244
1330
 
1245
1331
  if yarn?
@@ -1273,6 +1359,14 @@ module Squared
1273
1359
  %w[cpu os libc].each { |name| option(name) { |val| target << basic_option(name, val) } }
1274
1360
  end
1275
1361
 
1362
+ def quotepath(name, val)
1363
+ if $2.include?(File::SEPARATOR) || (workspace.windows? && val.match?(%r{[\\/]}))
1364
+ quote_option name, basepath(val)
1365
+ else
1366
+ shell_option name, val
1367
+ end
1368
+ end
1369
+
1276
1370
  def dependroot
1277
1371
  dependname if parent&.has?('outdated', Node.ref)
1278
1372
  end