squared 0.1.8 → 0.2.0

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.
@@ -8,7 +8,7 @@ module Squared
8
8
  def populate(*); end
9
9
 
10
10
  def tasks
11
- %i[outdated].freeze
11
+ [:outdated].freeze
12
12
  end
13
13
 
14
14
  def batchargs
@@ -35,11 +35,12 @@ module Squared
35
35
  end
36
36
 
37
37
  @@tasks[ref] = {
38
- install: %i[force frozen dedupe].freeze,
39
- outdated: %i[major minor patch].freeze,
40
- bump: %i[major minor patch].freeze,
41
- update: nil,
42
- run: nil
38
+ 'install' => %i[force frozen dedupe].freeze,
39
+ 'outdated' => %i[major minor patch].freeze,
40
+ 'bump' => %i[version major minor patch].freeze,
41
+ 'add' => nil,
42
+ 'update' => nil,
43
+ 'run' => nil
43
44
  }.freeze
44
45
 
45
46
  def initialize(*, **kwargs)
@@ -59,25 +60,45 @@ module Squared
59
60
  Node.ref
60
61
  end
61
62
 
62
- def populate(*)
63
+ def populate(*, **)
63
64
  super
64
65
  return unless outdated? && ref?(Node.ref)
65
66
 
66
67
  namespace name do
67
68
  @@tasks[Node.ref].each do |action, flags|
69
+ next if @pass.include?(action)
70
+
68
71
  if flags.nil?
69
72
  case action
70
- when :run
71
- desc format_desc(action, nil, 'command+|^index|#,pattern*')
73
+ when 'add'
74
+ format_desc action, nil, 'save?=prod|dev|optional|peer,name+'
75
+ task action, [:save, :name] do |_, args|
76
+ save = param_guard(action, 'save', args: args, key: :save)
77
+ if save.start_with?('=')
78
+ exact = true
79
+ save = save[1..-1]
80
+ end
81
+ case save
82
+ when 'prod', 'dev', 'optional', 'peer'
83
+ name = param_guard(action, 'name', args: args.to_a.drop(1))
84
+ else
85
+ save = 'prod'
86
+ name = param_guard(action, 'name', args: args.to_a)
87
+ end
88
+ depend(:add, packages: name, save: save, exact: exact)
89
+ end
90
+ when 'run'
91
+ next if (list = read_scripts).empty?
92
+
93
+ format_desc action, nil, 'command+|^index|#,pattern*'
72
94
  task action, [:command] do |_, args|
73
95
  if args.command == '#'
74
- format_list(read_scripts, 'run[^N]', 'scripts', grep: args.extras, from: dependfile.to_s)
96
+ format_list(list, 'run[^N]', 'scripts', grep: args.extras, from: dependfile.to_s)
75
97
  else
76
- cmd = guard_params(action, 'command', args: args.to_a)
98
+ cmd = param_guard(action, 'command', args: args.to_a)
77
99
  cmd.each do |val|
78
100
  if (data = indexitem(val))
79
101
  n, opts = data
80
- list = read_scripts
81
102
  if (item = list[n - 1])
82
103
  val = opts ? "#{item.first} #{opts}" : item.first
83
104
  elsif exception
@@ -90,9 +111,9 @@ module Squared
90
111
  end
91
112
  end
92
113
  end
93
- when :update
94
- desc format_desc(action, nil, 'packages*')
95
- task action, [:packages] do |_, args|
114
+ when 'update'
115
+ format_desc action, nil, 'packages*'
116
+ task action do |_, args|
96
117
  update args.to_a
97
118
  end
98
119
  end
@@ -100,20 +121,28 @@ module Squared
100
121
  namespace action do
101
122
  flags.each do |flag|
102
123
  case action
103
- when :install
104
- desc format_desc(action, flag)
124
+ when 'install'
125
+ format_desc action, flag
105
126
  task flag do
106
127
  depend flag
107
128
  end
108
- when :outdated
109
- desc format_desc(action, flag, %w[prune interactive dry-run].freeze, arg: 'opts?')
110
- task flag, [:opts] do |_, args|
129
+ when 'outdated'
130
+ format_desc(action, flag, %w[prune interactive dry-run].freeze, arg: 'opts?')
131
+ task flag do |_, args|
111
132
  outdated(flag, opts: args.to_a)
112
133
  end
113
- else
114
- desc format_desc(action, flag)
115
- task flag do
116
- __send__(action, flag)
134
+ when 'bump'
135
+ if flag == :version
136
+ format_desc action, flag, 'version'
137
+ task flag, [:version] do |_, args|
138
+ version = param_guard(action, flag, args: args, key: :version)
139
+ bump flag, version
140
+ end
141
+ else
142
+ format_desc action, flag
143
+ task flag do
144
+ bump flag
145
+ end
117
146
  end
118
147
  end
119
148
  end
@@ -123,8 +152,8 @@ module Squared
123
152
  end
124
153
  end
125
154
 
126
- def copy(from: 'build', into: 'node_modules', workspace: false, scope: nil,
127
- also: nil, create: nil, override: false, **kwargs)
155
+ def copy(from: 'build', into: 'node_modules', workspace: false, include: nil, exclude: nil, scope: nil,
156
+ also: nil, create: nil, link: false, force: false, override: false)
128
157
  return if @copy == false
129
158
 
130
159
  if @copy && !override
@@ -133,21 +162,21 @@ module Squared
133
162
  from = @copy[:from] if @copy.key?(:from)
134
163
  into = @copy[:into] if @copy.key?(:into)
135
164
  workspace = @copy[:workspace] if @copy.key?(:workspace)
165
+ link = @copy[:link] if @copy.key?(:link)
166
+ force = @copy[:force] if @copy.key?(:link)
136
167
  glob = @copy[:include]
137
168
  exclude = @copy[:exclude]
138
169
  scope = @copy[:scope]
139
170
  also = @copy[:also]
140
171
  create = @copy[:create]
141
- else
142
- glob = kwargs[:include]
143
- exclude = kwargs[:exclude]
144
172
  end
145
173
  items = []
146
174
  items << @workspace.home if build? && path != @workspace.home && @workspace.home?
147
175
  items += as_a(also) if also
148
176
  return if items.empty?
149
177
 
150
- print_item unless @output[0] || !verbose || task_invoked?(/\Acopy(?::#{Node.ref}|$)/)
178
+ on :first, :copy
179
+ print_item unless @output[0] || !verbose || task_invoked?(/^copy(?::#{Node.ref}|$)/)
151
180
  items.each do |dir|
152
181
  case dir
153
182
  when Pathname
@@ -163,6 +192,8 @@ module Squared
163
192
  from = dir[:from] if dir.key?(:from)
164
193
  into = dir[:into] if dir.key?(:into)
165
194
  scope = dir[:scope] if dir.key?(:scope)
195
+ link = dir[:link] if dir.key?(:link)
196
+ force = dir[:force] if dir.key?(:force)
166
197
  dest = dir[:target]
167
198
  create = dir[:create]
168
199
  workspace = dir[:workspace]
@@ -186,10 +217,11 @@ module Squared
186
217
  elsif (file = path.join('package.json')).exist?
187
218
  begin
188
219
  doc = JSON.parse(file.read)
189
- doc['name']
190
220
  rescue StandardError => e
191
221
  log.error e
192
222
  raise if exception
223
+ else
224
+ doc['name']
193
225
  end
194
226
  end
195
227
  if sub
@@ -203,18 +235,29 @@ module Squared
203
235
  end
204
236
  target.each do |src, to|
205
237
  glob.each { |val| log.info "cp #{from.join(val)} #{to}" }
206
- copy_d(src, to, glob: glob, create: create, pass: exclude, verbose: verbose)
238
+ begin
239
+ copy_dir(src, to, glob, create: create, link: link, force: force, pass: exclude, verbose: verbose)
240
+ rescue StandardError => e
241
+ log.error e
242
+ ret = on(:error, :copy, e)
243
+ raise if exception && ret != true
244
+ end
207
245
  end
208
246
  end
247
+ on :last, :copy
209
248
  end
210
249
 
211
- def depend(flag = nil, sync: invoked_sync?('depend', flag))
250
+ def depend(flag = nil, sync: invoked_sync?('depend', flag), packages: [], save: nil, exact: nil)
212
251
  if @depend && !flag
213
252
  super
214
253
  elsif outdated?
215
254
  if (yarn = dependtype(:yarn)) > 0
216
255
  cmd = session 'yarn'
217
- if yarn > 1
256
+ if flag == :add
257
+ cmd << 'add'
258
+ cmd << "--#{save}" unless save == 'prod'
259
+ cmd << '--exact' if exact
260
+ elsif yarn > 1
218
261
  if flag == :dedupe
219
262
  cmd << 'dedupe'
220
263
  else
@@ -235,7 +278,12 @@ module Squared
235
278
  end
236
279
  elsif pnpm?
237
280
  cmd = session 'pnpm'
238
- if flag == :dedupe
281
+ case flag
282
+ when :add
283
+ cmd << 'add'
284
+ cmd << "--save-#{save}"
285
+ cmd << '--save-exact' if exact
286
+ when :dedupe
239
287
  cmd << 'dedupe'
240
288
  else
241
289
  cmd << 'install' << if flag == :force
@@ -249,10 +297,15 @@ module Squared
249
297
  split_escape(val).each { |opt| cmd << shell_option('public-hoist-pattern', opt, quote: true) }
250
298
  end
251
299
  cmd << '--ignore-workspace' if env('NODE_WORKSPACES', equals: '0')
252
- append_nocolor option('no-color')
300
+ append_nocolor
253
301
  else
254
302
  cmd = session 'npm'
255
- if flag == :dedupe
303
+ case flag
304
+ when :add
305
+ cmd << 'install'
306
+ cmd << "--save-#{save}"
307
+ cmd << '--save-exact' if exact
308
+ when :dedupe
256
309
  cmd << 'dedupe'
257
310
  else
258
311
  cmd << 'install' << if flag == :force
@@ -261,34 +314,41 @@ module Squared
261
314
  '--package-lock-only'
262
315
  end
263
316
  end
264
- cmd << '--omit=dev' if flag && prod?
317
+ if flag == :add
318
+ cmd.merge(packages.map { |pkg| shell_escape(pkg) })
319
+ elsif flag && prod?
320
+ cmd << '--omit=dev'
321
+ end
265
322
  cmd << '--workspaces=false' if env('NODE_WORKSPACES', equals: '0')
266
323
  cmd << '--package-lock=false' if option('package-lock', equals: '0')
267
- append_nocolor option('no-color')
324
+ append_nocolor
268
325
  end
269
326
  append_loglevel
270
- run(sync: sync)
327
+ run(from: :depend, sync: sync)
271
328
  end
272
329
  end
273
330
 
274
- def outdated(rev = nil, opts: [], sync: invoked_sync?('outdated', rev))
331
+ def outdated(flag = nil, sync: invoked_sync?('outdated', flag), opts: [])
275
332
  dryrun = opts.include?('dry-run')
276
- if pnpm? && read_packagemanager(version: '7.15')
277
- cmd = 'pnpm outdated'
333
+ if pnpm? && read_packagemanager(version: '7.15', update: true)
334
+ cmd = session 'pnpm', 'outdated'
278
335
  dryrun ||= dryrun?('pnpm')
279
336
  else
280
- cmd = 'npm outdated'
337
+ cmd = session 'npm', 'outdated'
281
338
  dryrun ||= dryrun?('npm')
282
339
  end
283
- log.info cmd
284
- banner = format_banner("#{cmd}#{dryrun ? ' --dry-run' : ''}")
340
+ log.info cmd.to_s
341
+ on :first, :outdated unless dryrun
342
+ banner = format_banner(cmd.temp(dryrun ? ' --dry-run' : nil))
285
343
  print_item banner if sync
286
344
  begin
287
- data = pwd_set { `#{cmd} --json --loglevel=error` }
288
- json = JSON.parse(doc = dependfile.read)
345
+ data = pwd_set { `#{cmd.temp('--json', '--loglevel=error')}` }
346
+ doc = dependfile.read
347
+ json = JSON.parse(doc)
289
348
  rescue StandardError => e
290
349
  log.error e
291
- raise if exception
350
+ ret = on(:error, :outdated, e)
351
+ raise if exception && ret != true
292
352
 
293
353
  warn log_message(Logger::WARN, e) if warning?
294
354
  return
@@ -299,7 +359,7 @@ module Squared
299
359
  end
300
360
  found = []
301
361
  avail = []
302
- rev ||= (prod? ? :patch : :minor)
362
+ rev = flag || (prod? ? :patch : :minor)
303
363
  inter = opts.include?('interactive')
304
364
  unless data.empty?
305
365
  JSON.parse(data).each_pair do |key, val|
@@ -340,7 +400,7 @@ module Squared
340
400
  index = if a != c
341
401
  1
342
402
  elsif b != d
343
- a == '0' ? 1 : 3
403
+ 3
344
404
  else
345
405
  5
346
406
  end
@@ -357,7 +417,7 @@ module Squared
357
417
  ret = val.succ.to_s
358
418
  ord.size > 9 ? ret.rjust(ord.size.to_s.size) : ret
359
419
  end
360
- footer = lambda do |val = 0|
420
+ footer = lambda do |val, size|
361
421
  next unless verbose
362
422
 
363
423
  msg, hint = if modified == -1
@@ -365,7 +425,8 @@ module Squared
365
425
  else
366
426
  ['No packages were updated', 'possible']
367
427
  end
368
- puts print_footer(empty_status(msg, hint, pending + val))
428
+ possible = pending + val
429
+ puts print_footer(empty_status(msg, hint, possible == size ? 0 : possible))
369
430
  end
370
431
  print_item banner unless sync
371
432
  if !found.empty?
@@ -373,8 +434,7 @@ module Squared
373
434
  col2 = size_col.(found, 1) + 4
374
435
  found.each_with_index do |item, i|
375
436
  a, b, c, d, e = item
376
- f = inter && (rev != :major || e || semmajor?(item[5], item[6]))
377
- if f && !confirm_outdated(a, c, d, e)
437
+ if inter && (rev != :major || e || semmajor?(item[5], item[6])) && !confirm_outdated(a, c, d, e)
378
438
  cur = -1
379
439
  else
380
440
  cur = modified
@@ -390,6 +450,8 @@ module Squared
390
450
  end
391
451
  end
392
452
  a = a.ljust(col1)
453
+ b = b.ljust(col2)
454
+ b = sub_style(b, styles: theme[:current]) if theme[:current]
393
455
  c = if cur == -1
394
456
  'SKIP'
395
457
  elsif modified == cur
@@ -400,14 +462,14 @@ module Squared
400
462
  else
401
463
  sub_style(c, pat: SEM_VER, styles: color(:green), index: d)
402
464
  end
403
- puts "#{pad_ord.(i, found)}. #{a}#{b.ljust(col2)}#{c}"
465
+ puts "#{pad_ord.(i, found)}. #{a + b + c}"
404
466
  end
405
467
  pending = avail.reduce(pending) { |a, b| a + (b[3] ? 0 : 1) }
406
468
  if dryrun || (modified == 0 && pending > 0)
407
- footer.(modified)
469
+ footer.(modified, found.size)
408
470
  elsif modified > 0
409
471
  modified = -1
410
- footer.()
472
+ footer.(0, found.size)
411
473
  File.write(dependfile, doc)
412
474
  commit(:add, ['package.json'], pass: true)
413
475
  install if opts.include?('prune')
@@ -428,51 +490,58 @@ module Squared
428
490
  end
429
491
  puts "#{pad_ord.(i, avail)}. #{a + c + b} (#{d ? 'locked' : 'latest'})"
430
492
  end
431
- footer.()
493
+ footer.(0, avail.size)
432
494
  else
433
495
  puts 'No updates were found'
434
496
  end
497
+ on :last, :outdated unless dryrun
435
498
  end
436
499
 
437
- def bump(flag = nil)
438
- return unless (ver = version)
500
+ def bump(flag, val = nil)
501
+ return unless (cur = version)
439
502
 
440
- seg = semscan(ver, fill: false)
441
- case flag
442
- when :major
443
- if seg[0] != '0' || seg[2].nil?
444
- seg[0] = seg[0].succ
445
- else
446
- seg[2] = seg[2].succ
447
- end
448
- when :minor
449
- if seg[0] == '0'
503
+ if flag == :version
504
+ return unless val
505
+ else
506
+ seg = semscan(cur, fill: false)
507
+ case flag
508
+ when :major
509
+ if seg[0] != '0' || seg[2].nil?
510
+ seg[0] = seg[0].succ
511
+ else
512
+ seg[2] = seg[2].succ
513
+ end
514
+ when :minor
515
+ if seg[0] == '0'
516
+ seg[4] &&= seg[4].succ
517
+ else
518
+ seg[2] = seg[2].succ
519
+ end
520
+ when :patch
450
521
  seg[4] &&= seg[4].succ
451
- else
452
- seg[2] = seg[2].succ
453
522
  end
454
- else
455
- seg[4] &&= seg[4].succ
523
+ return if (val = seg.join) == cur
456
524
  end
457
- return if (out = seg.join) == ver
458
525
 
459
526
  begin
460
527
  doc = dependfile.read
461
- if doc.sub!(/"version"\s*:\s*"#{ver}"/, "\"version\": \"#{out}\"")
528
+ if doc.sub!(/"version"\s*:\s*"#{cur}"/, "\"version\": \"#{val}\"")
462
529
  unless dryrun?
463
530
  dependfile.write(doc)
464
- log.info "bump version #{ver} to #{out} (#{flag})"
531
+ log.info "bump version #{cur} to #{val} (#{flag})"
532
+ on :first, :bump
465
533
  end
466
534
  if verbose
467
535
  major = flag == :major
468
- emphasize("version: #{out}", title: name, border: borderstyle, sub: [
536
+ emphasize("version: #{val}", title: name, border: borderstyle, sub: [
469
537
  headerstyle,
470
538
  { pat: /\A(version:)( )(\S+)(.*)\z/, styles: color(major ? :green : :yellow), index: 3 },
471
539
  { pat: /\A(version:)(.*)\z/, styles: theme[major ? :major : :active] }
472
540
  ])
473
541
  elsif stdin?
474
- puts out
542
+ puts val
475
543
  end
544
+ on :last, :bump unless dryrun?
476
545
  else
477
546
  raise_error('not found', hint: 'version')
478
547
  end
@@ -494,19 +563,19 @@ module Squared
494
563
  elsif pnpm?
495
564
  cmd = session 'pnpm', 'update'
496
565
  cmd << '--prod' if prod?
497
- append_nocolor option('no-color')
566
+ append_nocolor
498
567
  else
499
568
  cmd = session 'npm', 'update'
500
569
  cmd << '--omit=dev' if prod?
501
- append_nocolor option('no-color')
570
+ append_nocolor
502
571
  end
503
572
  append_loglevel
504
573
  append_value pkgs
505
574
  run
506
575
  end
507
576
 
508
- def compose(opts, flags = nil, script: false)
509
- return unless opts && script
577
+ def compose(opts, flags = nil, script: false, from: :build)
578
+ return unless opts && script && from == :build
510
579
 
511
580
  ret = session dependbin, 'run', flags
512
581
  append_loglevel
@@ -516,7 +585,7 @@ module Squared
516
585
  when String
517
586
  ret << opts
518
587
  else
519
- raise_error("#{ret.first} script name", hint: opts.nil? ? 'missing' : 'invalid')
588
+ raise_error("#{dependbin} script name", hint: opts.nil? ? 'missing' : 'invalid')
520
589
  end
521
590
  ret
522
591
  end
@@ -533,10 +602,6 @@ module Squared
533
602
  dependfile.exist?
534
603
  end
535
604
 
536
- def refresh?
537
- !Node.prod?
538
- end
539
-
540
605
  def yarn?
541
606
  (@pm[:yarn] ||= if basepath('yarn.lock', ascend: dependext).exist?
542
607
  if (rc = basepath('.yarnrc.yml', ascend: dependext)).exist?
@@ -544,13 +609,14 @@ module Squared
544
609
  require 'yaml'
545
610
  doc = YAML.load_file(rc)
546
611
  doc.nodeLinker == 'node-modules' ? 2 : 3
547
- rescue StandardError
612
+ rescue StandardError => e
613
+ log.debug e
548
614
  3
549
615
  end
550
616
  else
551
617
  1
552
618
  end
553
- elsif (ver = read_packagemanager || read_install) && ver.start_with?('yarn')
619
+ elsif (ver = read_packagemanager || read_install)&.start_with?('yarn')
554
620
  ver == 'yarn' || ver.include?('@1') ? 1 : 3
555
621
  else
556
622
  0
@@ -571,7 +637,8 @@ module Squared
571
637
  else
572
638
  4
573
639
  end
574
- rescue StandardError
640
+ rescue StandardError => e
641
+ log.debug e
575
642
  4
576
643
  end
577
644
  else
@@ -583,8 +650,7 @@ module Squared
583
650
  if pnpm?
584
651
  basepath('pnpm-workspace.yaml').exist?
585
652
  else
586
- read_packagemanager
587
- @pm[:workspaces].is_a?(Array)
653
+ read_packagemanager(:workspaces).is_a?(Array)
588
654
  end
589
655
  end
590
656
 
@@ -604,19 +670,17 @@ module Squared
604
670
  end
605
671
 
606
672
  def version
607
- read_packagemanager
608
- @pm[:version]
673
+ super || (@version = read_packagemanager(:version))
609
674
  end
610
675
 
611
676
  def packagename
612
- read_packagemanager
613
- @pm[:name]
677
+ read_packagemanager :name
614
678
  end
615
679
 
616
680
  private
617
681
 
618
- def read_packagemanager(version: nil)
619
- if @pm[:_].nil?
682
+ def read_packagemanager(key = nil, version: nil, update: false)
683
+ if @pm[:_].nil? || update
620
684
  doc = JSON.parse(dependfile.read)
621
685
  @pm[:_] = (val = doc['packageManager']) ? val[0..(val.index('+') || 0) - 1] : false
622
686
  @pm[:name] = doc['name']
@@ -625,10 +689,12 @@ module Squared
625
689
  @pm[:workspaces] = doc['workspaces']
626
690
  end
627
691
  rescue StandardError => e
628
- log.debug e if dependfile.exist?
692
+ log.debug e
629
693
  @pm[:_] = false
630
694
  nil
631
695
  else
696
+ return @pm[key] if key
697
+
632
698
  !(ret = @pm[:_]) || (version && ret[ret.index('@') + 1..-1] < version) ? nil : ret
633
699
  end
634
700
 
@@ -640,11 +706,11 @@ module Squared
640
706
  end
641
707
 
642
708
  def read_scripts
643
- read_packagemanager
644
- @pm[:scripts].is_a?(Hash) ? @pm[:scripts].to_a : []
709
+ ret = read_packagemanager(:scripts)
710
+ ret.is_a?(Hash) ? ret.to_a : []
645
711
  end
646
712
 
647
- def append_loglevel
713
+ def append_loglevel(target: @session)
648
714
  level = env('NODE_LOGLEVEL')
649
715
  silent = !verbose || level == 'silent'
650
716
  return unless silent || level
@@ -652,26 +718,26 @@ module Squared
652
718
  if yarn?
653
719
  if dependtype(:yarn) == 1
654
720
  if silent
655
- @session << '--silent'
721
+ target << '--silent'
656
722
  elsif level == 'verbose'
657
- @session << '--verbose'
723
+ target << '--verbose'
658
724
  end
659
725
  end
660
726
  elsif pnpm?
661
727
  if silent
662
- @session << shell_option('reporter', 'silent', escape: false)
728
+ target << '--reporter=silent'
663
729
  level ||= 'error'
664
730
  end
665
731
  case level
666
732
  when 'debug', 'info', 'warn', 'error'
667
- @session << shell_option('loglevel', level, escape: false)
733
+ target << basic_option('loglevel', level)
668
734
  end
669
735
  elsif silent
670
- @session << shell_option('loglevel', 'silent', escape: false)
736
+ target << '--loglevel=silent'
671
737
  else
672
738
  case level
673
739
  when 'error', 'warn', 'notice', 'http', 'info', 'verbose', 'silly'
674
- @session << shell_option('loglevel', level, escape: false)
740
+ target << basic_option('loglevel', level)
675
741
  end
676
742
  end
677
743
  end
@@ -692,7 +758,7 @@ module Squared
692
758
  end
693
759
 
694
760
  def dryrun?(prefix = dependbin)
695
- !option('dry-run', prefix: prefix).nil?
761
+ super || !option('dry-run', prefix: prefix).nil?
696
762
  end
697
763
 
698
764
  def dependbin