squared 0.0.10 → 0.0.12

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,30 +8,39 @@ module Squared
8
8
  def populate(*); end
9
9
 
10
10
  def tasks
11
- nil
11
+ %i[outdated].freeze
12
+ end
13
+
14
+ def batchargs
15
+ [ref, { refresh: %i[build copy] }]
16
+ end
17
+
18
+ def aliasargs
19
+ [ref, { refresh: :build }]
20
+ end
21
+
22
+ def bannerargs
23
+ %i[version dependfile].freeze
12
24
  end
13
25
 
14
26
  def prod?
15
27
  ENV['NODE_ENV'] == 'production'
16
28
  end
17
29
 
18
- def is_a?(val)
19
- if (val = as_path(val))
20
- val.join('package.json').exist?
21
- else
22
- super
23
- end
30
+ def config?(val)
31
+ return false unless (val = as_path(val))
32
+
33
+ val.join('package.json').exist?
24
34
  end
25
35
  end
26
36
 
27
37
  @@tasks[ref] = {
28
- install: %i[force frozen dedupe],
29
- outdated: %i[major minor patch],
38
+ install: %i[force frozen dedupe].freeze,
39
+ outdated: %i[major minor patch].freeze,
40
+ bump: %i[major minor patch].freeze,
30
41
  run: nil
31
42
  }.freeze
32
43
 
33
- attr_reader :package
34
-
35
44
  def initialize(*, **kwargs)
36
45
  super
37
46
  if @pass.include?(Node.ref)
@@ -42,7 +51,7 @@ module Squared
42
51
  initialize_env(**kwargs)
43
52
  end
44
53
  @pm = {}
45
- @package = base_path('package.json')
54
+ @dependfile = basepath('package.json')
46
55
  end
47
56
 
48
57
  def ref
@@ -58,11 +67,27 @@ 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
+ format_list(read_scripts, 'run[^N]', 'scripts', grep: args.extras, from: dependfile.to_s)
74
+ else
75
+ cmd = guard_params(action, 'command', args: args.to_a)
76
+ cmd.each do |val|
77
+ if (data = indexdata(val))
78
+ n, opts = data
79
+ list = read_scripts
80
+ if (item = list[n - 1])
81
+ val = opts ? "#{item.first} #{opts}" : item.first
82
+ elsif exception
83
+ indexerror n, list
84
+ else
85
+ next log.warn "run script #{n} of #{list.size} (out of range)"
86
+ end
87
+ end
88
+ run compose(val, script: true)
89
+ end
90
+ end
66
91
  end
67
92
  end
68
93
  else
@@ -75,10 +100,15 @@ module Squared
75
100
  depend(flag)
76
101
  end
77
102
  when :outdated
78
- desc format_desc(action, flag, %w[prune interactive dry-run], arg: 'opts?')
103
+ desc format_desc(action, flag, %w[prune interactive dry-run].freeze, arg: 'opts?')
79
104
  task flag, [:opts] do |_, args|
80
105
  outdated(flag, opts: args.to_a)
81
106
  end
107
+ else
108
+ desc format_desc(action, flag)
109
+ task flag do
110
+ __send__(action, flag)
111
+ end
82
112
  end
83
113
  end
84
114
  end
@@ -87,17 +117,19 @@ module Squared
87
117
  end
88
118
  end
89
119
 
90
- def copy(from: 'build', glob: '**/*', subdir: 'node_modules', into: nil, also: nil, override: false)
120
+ def copy(from: 'build', glob: nil, into: 'node_modules', scope: nil, also: nil, override: false)
121
+ return if @copy == false
122
+
91
123
  if @copy && !override
92
124
  return super if runnable?(@copy)
93
125
 
94
126
  from = @copy[:from] if @copy.key?(:from)
95
127
  glob = @copy[:glob] if @copy.key?(:glob)
96
- subdir = @copy[:subdir] if @copy.key?(:subdir)
97
128
  into = @copy[:into] if @copy.key?(:into)
129
+ scope = @copy[:scope] if @copy.key?(:scope)
98
130
  also = @copy[:also] if @copy.key?(:also)
99
131
  end
100
- items = [path == workspace.home ? nil : workspace.home]
132
+ items = [path != workspace.home && workspace.home? ? workspace.home : nil]
101
133
  items += as_a(also) if also
102
134
  items.each_with_index do |dir, i|
103
135
  if i == 0
@@ -107,46 +139,38 @@ module Squared
107
139
  else
108
140
  case dir
109
141
  when ::String
110
- dest = workspace.root_path(dir)
142
+ dest = workspace.rootpath(dir)
111
143
  when ::Symbol
112
- dest = Workspace.resolve(dir)&.path
144
+ dest = workspace.find(name: dir)&.path
145
+ log.warn message("copy project :#{dir}", hint: 'not found') unless dest
113
146
  when ::Hash
114
- glob = '**/*'
115
- dest = nil
116
- into = nil
117
- dir.each do |key, val|
118
- case key.to_sym
119
- when :target
120
- dest = val
121
- when :from
122
- from = val
123
- when :glob
124
- glob = val
125
- when :subdir
126
- subdir = val
127
- when :into
128
- into = val
129
- end
130
- end
147
+ missing = ->(val) { log.warn message("copy attr :#{val}", hint: 'missing') }
148
+ glob = dir[:glob]
149
+ into = dir[:into] if dir.key?(:into)
150
+ scope = dir[:scope]
151
+ missing.('target') unless (dest = dir[:target])
152
+ missing.('from') unless (from = dir[:from])
131
153
  when Project::Base
132
154
  dest = dir.path
155
+ else
156
+ raise_error("given: #{dir}", hint: 'unknown')
133
157
  end
134
- next unless into
135
158
  end
136
- next unless dest&.directory?
159
+ next unless from && dest&.directory?
137
160
 
138
- from = base_path(from)
139
- dest = dest.join(subdir, into || project)
140
- log.warn "cp #{from.join(glob)} #{dest}"
161
+ from = basepath(from)
162
+ dest = dest.join(into, scope || project)
163
+ glob = as_a(glob || '**/*')
164
+ glob.each { |val| log.info "cp #{from.join(val)} #{dest}" }
141
165
  copy_d(from, dest, glob: glob, verbose: verbose)
142
166
  end
143
167
  end
144
168
 
145
- def depend(flag = nil)
169
+ def depend(flag = nil, sync: invoked_sync?('depend', flag))
146
170
  if @depend && !flag
147
171
  super
148
172
  elsif outdated?
149
- if (yarn = install_type(:yarn)) > 0
173
+ if (yarn = dependtype(:yarn)) > 0
150
174
  cmd = session 'yarn'
151
175
  if yarn > 1
152
176
  if flag == :dedupe
@@ -165,7 +189,7 @@ module Squared
165
189
  '--frozen-lockfile'
166
190
  end
167
191
  cmd << '--production' if flag && prod?
168
- cmd << '--ignore-engines' unless env('YARN_IGNORE_ENGINES', equals: '0')
192
+ cmd << '--ignore-engines' unless option('ignore-engines', equals: '0')
169
193
  end
170
194
  elsif pnpm?
171
195
  cmd = session 'pnpm'
@@ -179,11 +203,11 @@ module Squared
179
203
  end
180
204
  end
181
205
  cmd << '--prod' if flag && prod?
182
- if (val = env('PNPM_PUBLIC_HOIST_PATTERN'))
206
+ if (val = option('public-hoist-pattern', ignore: false))
183
207
  split_escape(val).each { |opt| cmd << "--public-hoist-pattern=#{shell_escape(opt, quote: true)}" }
184
208
  end
185
209
  cmd << '--ignore-workspace' if env('NODE_WORKSPACES', equals: '0')
186
- append_nocolor
210
+ append_nocolor option('no-color')
187
211
  else
188
212
  cmd = session 'npm'
189
213
  if flag == :dedupe
@@ -197,26 +221,32 @@ module Squared
197
221
  end
198
222
  cmd << '--omit=dev' if flag && prod?
199
223
  cmd << '--workspaces=false' if env('NODE_WORKSPACES', equals: '0')
200
- cmd << '--package-lock=false' if env('NPM_PACKAGE_LOCK', equals: '0')
201
- append_nocolor
224
+ cmd << '--package-lock=false' if option('package-lock', equals: '0')
225
+ append_nocolor option('no-color')
202
226
  end
203
227
  append_loglevel
204
- run(sync: invoked_sync?('depend', flag))
228
+ run(sync: sync)
205
229
  end
206
230
  end
207
231
 
208
232
  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'
233
+ dryrun = opts.include?('dry-run')
234
+ if pnpm? && read_packagemanager(version: '7.15')
235
+ cmd = 'pnpm outdated'
236
+ dryrun ||= !option('dry-run', prefix: 'pnpm').nil?
237
+ else
238
+ cmd = 'npm outdated'
239
+ dryrun ||= !option('dry-run', prefix: 'npm').nil?
240
+ end
211
241
  log.info cmd
212
- banner = format_banner("#{cmd}#{dryrun ? ' --dry-run' : ''}", multiple: true)
242
+ banner = format_banner("#{cmd}#{dryrun ? ' --dry-run' : ''}")
213
243
  if invoked_sync?('outdated', rev)
214
244
  print_item banner
215
245
  banner = nil
216
246
  end
217
247
  data = nil
218
248
  pwd_set { data = `#{cmd} --json --loglevel=error` }
219
- json = JSON.parse(doc = package.read)
249
+ json = JSON.parse(doc = dependfile.read)
220
250
  dep1 = json['dependencies'] || {}
221
251
  dep2 = json['devDependencies'] || {}
222
252
  found = []
@@ -226,7 +256,7 @@ module Squared
226
256
  unless data.empty?
227
257
  JSON.parse(data).each_pair do |key, val|
228
258
  val = val.find { |obj| obj['dependent'] == json['name'] } if val.is_a?(::Array)
229
- next unless val && (file = dep1[key] || dep2[key])
259
+ next unless val && (file = dep1[key] || dep2[key]) && file != '*'
230
260
 
231
261
  latest = val['latest']
232
262
  ch = file[0]
@@ -238,18 +268,18 @@ module Squared
238
268
  avail << [key, file, latest, true]
239
269
  next
240
270
  end
241
- want = rev == :major && latest.match(SEM_VER) && !Regexp.last_match(6) ? latest : val['wanted']
271
+ want = rev == :major && (ver = latest.match(SEM_VER)) && !ver[6] ? latest : val['wanted']
242
272
  next unless (val['current'] != want || file != want) && (want.match?(SEM_VER) || !file.match?(SEM_VER))
243
273
 
244
- f = semver(file.scan(SEM_VER)).first
245
- w = semver(want.scan(SEM_VER)).first
274
+ f = semver(semscan(file))
275
+ w = semver(semscan(want))
246
276
  a = f[0]
247
277
  b = f[2]
248
278
  c = w[0]
249
279
  d = w[2]
250
280
  case rev
251
281
  when :major
252
- upgrade = a == '0' ? c == '0' : true
282
+ upgrade = a == '0' ? c == '0' || c == '1' : true
253
283
  when :minor
254
284
  upgrade = ch == '^' && (a == '0' ? c == '0' && b == d : a == c)
255
285
  when :patch
@@ -294,7 +324,7 @@ module Squared
294
324
  col2 = size_col.(found, 1) + 4
295
325
  found.each_with_index do |item, i|
296
326
  a, b, c, d, e = item
297
- if inter && (rev != :major || e || semmajor(item[5], item[6])) && !confirm_outdated(a, c, d)
327
+ if inter && (rev != :major || e || semmajor?(item[5], item[6])) && !confirm_outdated(a, c, d, e)
298
328
  cur = -1
299
329
  else
300
330
  cur = modified
@@ -326,10 +356,10 @@ module Squared
326
356
  if dryrun || (modified == 0 && pending > 0)
327
357
  footer.(modified)
328
358
  elsif modified > 0
329
- File.write(package, doc)
359
+ File.write(dependfile, doc)
330
360
  modified = -1
331
361
  footer.()
332
- commit(:add, 'package.json', pass: true)
362
+ commit(:add, ['package.json'], pass: true)
333
363
  install if opts.include?('prune')
334
364
  end
335
365
  elsif !avail.empty?
@@ -354,12 +384,14 @@ module Squared
354
384
  end
355
385
  end
356
386
 
357
- def compose(opts)
387
+ def compose(opts, flags = nil, script: false)
388
+ return unless opts && script
389
+
358
390
  ret = session (if yarn?
359
391
  'yarn'
360
392
  else
361
393
  pnpm? ? 'pnpm' : 'npm'
362
- end), 'run'
394
+ end), 'run', flags
363
395
  append_loglevel
364
396
  case opts
365
397
  when ::Enumerable
@@ -372,11 +404,66 @@ module Squared
372
404
  ret
373
405
  end
374
406
 
375
- def install_type(prog = nil)
376
- prog ||= yarn? ? :yarn : :pnpm
377
- key = :"#{prog}?"
378
- __send__(key) if respond_to?(key)
379
- @pm[prog] || 0
407
+ def bump(flag)
408
+ return unless (ver = version)
409
+
410
+ seg = semscan(ver)
411
+ case flag
412
+ when :major
413
+ if seg[0] != '0' || seg[2].nil?
414
+ seg[0] = seg[0].succ
415
+ else
416
+ seg[2] = seg[2].succ
417
+ end
418
+ when :minor
419
+ if seg[0] == '0'
420
+ seg[4] &&= seg[4].succ
421
+ else
422
+ seg[2] = seg[2].succ
423
+ end
424
+ when :patch
425
+ seg[4] &&= seg[4].succ
426
+ end
427
+ unless (out = seg.join) == ver
428
+ begin
429
+ doc = dependfile.read
430
+ if doc.sub!(/"version"\s*:\s*"#{ver}"/, "\"version\": \"#{out}\"")
431
+ dependfile.write(doc)
432
+ log.info "bump version #{ver} to #{out} (#{flag})"
433
+ if verbose
434
+ major = flag == :major
435
+ emphasize("version: #{out}", title: name, border: borderstyle, sub: [
436
+ headerstyle,
437
+ { pat: /^(version:)( )(\S+)(.*)$/, styles: color(major ? :green : :yellow), index: 3 },
438
+ { pat: /^(version:)(.*)$/, styles: theme[major ? :major : :active] }
439
+ ])
440
+ elsif stdin?
441
+ puts out
442
+ end
443
+ else
444
+ raise_error('not found', hint: 'version')
445
+ end
446
+ rescue StandardError => e
447
+ log.debug e
448
+ raise
449
+ end
450
+ end
451
+ end
452
+
453
+ def version
454
+ read_packagemanager
455
+ @pm[:version]
456
+ end
457
+
458
+ def dependtype(prog)
459
+ return @pm[prog] if @pm.key?(prog)
460
+
461
+ meth = :"#{prog}?"
462
+ respond_to?(meth) && __send__(meth) ? @pm[prog] : 0
463
+ end
464
+
465
+ def depend?
466
+ @depend != false && (!@depend.nil? || outdated?)
380
467
  end
381
468
 
382
469
  def copy?
@@ -384,12 +471,12 @@ module Squared
384
471
  end
385
472
 
386
473
  def outdated?
387
- package.exist?
474
+ dependfile.exist?
388
475
  end
389
476
 
390
477
  def yarn?
391
- (@pm[:yarn] ||= if base_path('yarn.lock').exist?
392
- if (rc = base_path('.yarnrc.yml')).exist?
478
+ (@pm[:yarn] ||= if basepath('yarn.lock', ascend: find_package).exist?
479
+ if (rc = basepath('.yarnrc.yml', ascend: find_package)).exist?
393
480
  begin
394
481
  require 'yaml'
395
482
  doc = YAML.load_file(rc)
@@ -408,10 +495,10 @@ module Squared
408
495
  end
409
496
 
410
497
  def pnpm?
411
- (@pm[:pnpm] ||= if base_path('pnpm-lock.yaml').exist?
498
+ (@pm[:pnpm] ||= if basepath('pnpm-lock.yaml', ascend: find_package).exist?
412
499
  begin
413
500
  require 'yaml'
414
- doc = YAML.load_file(base_path('node_modules/.modules.yaml'))
501
+ doc = YAML.load_file(basepath('node_modules/.modules.yaml', ascend: find_package))
415
502
  @pm[:_] = doc['packageManager']
416
503
  case doc['nodeLinker']
417
504
  when 'hoisted'
@@ -429,6 +516,15 @@ module Squared
429
516
  end) > 0
430
517
  end
431
518
 
519
+ def workspaces?
520
+ if pnpm?
521
+ basepath('pnpm-workspace.yaml').exist?
522
+ else
523
+ read_packagemanager
524
+ @pm[:workspaces].is_a?(::Array)
525
+ end
526
+ end
527
+
432
528
  def dev?
433
529
  !Node.prod? && super
434
530
  end
@@ -439,13 +535,41 @@ module Squared
439
535
 
440
536
  private
441
537
 
538
+ def read_packagemanager(version: nil)
539
+ if @pm[:_].nil?
540
+ doc = JSON.parse(dependfile.read)
541
+ @pm[:_] = (val = doc['packageManager']) ? val[0..(val.index('+') || 0) - 1] : false
542
+ @pm[:scripts] = doc['scripts']
543
+ @pm[:version] = doc['version']
544
+ @pm[:workspaces] = doc['workspaces']
545
+ end
546
+ rescue StandardError => e
547
+ log.debug e if dependfile.exist?
548
+ @pm[:_] = false
549
+ nil
550
+ else
551
+ !(ret = @pm[:_]) || (version && ret[ret.index('@') + 1..-1] < version) ? nil : ret
552
+ end
553
+
554
+ def read_install
555
+ return unless (ret = env('NODE_INSTALL'))
556
+
557
+ @pm[:_] ||= ret if ret.include?('@')
558
+ ret
559
+ end
560
+
561
+ def read_scripts
562
+ read_packagemanager
563
+ @pm[:scripts].is_a?(::Hash) ? @pm[:scripts].to_a : []
564
+ end
565
+
442
566
  def append_loglevel
443
567
  level = env('NODE_LOGLEVEL')
444
568
  silent = !verbose || level == 'silent'
445
569
  return unless silent || level
446
570
 
447
571
  if yarn?
448
- if install_type(:yarn) == 1
572
+ if dependtype(:yarn) == 1
449
573
  if silent
450
574
  @session << '--silent'
451
575
  elsif level == 'verbose'
@@ -471,43 +595,27 @@ module Squared
471
595
  end
472
596
  end
473
597
 
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])
598
+ def confirm_outdated(pkg, ver, rev, lock)
599
+ a = sub_style(case rev
600
+ when 1
601
+ 'MAJOR'
602
+ when 3
603
+ 'MINOR'
604
+ else
605
+ 'PATCH'
606
+ end, styles: theme[:header])
484
607
  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)
487
- end
488
-
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[:_]
608
+ c, d = rev == 1 || lock ? %w[y/N N] : %w[Y/n Y]
609
+ e = lock ? " #{sub_style('(locked)', styles: color(:red))}" : ''
610
+ Common::Prompt.confirm("Upgrade to #{a}? #{b}#{e} [#{c}] ", d, timeout: 60)
502
611
  end
503
612
 
504
- def read_install
505
- return unless (ret = env('NODE_INSTALL'))
506
-
507
- @pm[:_] ||= ret if ret.include?('@')
508
- ret
613
+ def find_package
614
+ 'package.json' if parent&.has?('outdated', Node.ref)
509
615
  end
510
616
  end
617
+
618
+ Application.implement Node
511
619
  end
512
620
  end
513
621
  end