squared 0.7.5 → 0.7.7

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,15 +6,18 @@ module Squared
6
6
  class Node < Git
7
7
  OPT_NPM = {
8
8
  common: %w[dry-run=!? force=!? loglevel=b include-workspace-root=!? workspaces=!? w|workspace=v].freeze,
9
+ common_scripts: %w[dangerously-allow-all-scripts=!? strict-allow-scripts=!? allow-scripts=q].freeze,
9
10
  install: %w[package-lock-only=!? prefer-dedupe=!? E|save-exact=!? before=q cpu=b libc=b os=b].freeze,
10
11
  install_a: %w[audit=! bin-links=! foreground-scripts=!? fund=! ignore-scripts=!? install-links=!?
11
12
  package-lock=! strict-peer-deps=!? include=b install-strategy=b omit=b].freeze,
12
13
  install_b: %w[no-save B|save-bundle D|save-dev O|save-optional save-peer P|save-prod g|global=!?
13
14
  S|save=!?].freeze,
15
+ install_c: %w[allow-directory=b? allow-file=b? allow-git=b? allow-remote=b?].freeze,
14
16
  run: %w[foreground-scripts=!? if-present=!? ignore-scripts=!? script-shell=p].freeze,
15
17
  exec: %w[c|call=q package=b].freeze,
16
18
  pack: %w[ignore-scripts=!? json=!? pack-destination=p].freeze,
17
19
  rebuild: %w[bin-links=! foreground-scripts=!? global=!? ignore-scripts=!? install-links=!?].freeze,
20
+ 'approve-scripts': %w[a|all allow-scripts-pending allow-scripts-pin=!? no-allow-scripts-pin json].freeze,
18
21
  no: {
19
22
  install: %w[audit bin-links fund package-lock].freeze
20
23
  }.freeze
@@ -26,15 +29,16 @@ module Squared
26
29
  common_filter: %w[fail-if-no-match changed-files-ignore-pattern=q filter=q filter-prod=q
27
30
  test-pattern=q].freeze,
28
31
  install: %w[fix-lockfile force ignore-pnpmfile ignore-workspace lockfile-only merge-git-branch-lockfiles
29
- optimistic-repeat-install no-hoist no-lockfile no-optional prefer-frozen-lockfile resolution-only
30
- shamefully-hoist side-effects-cache side-effects-cache-readonly s|silent strict-peer-dependencies
31
- use-running-store-server use-store-server child-concurrency=i hoist-pattern=q lockfile-dir=p
32
- modules-dir=p network-concurrency=i package-import-method=b public-hoist-pattern=q
33
- reporter=b].freeze,
32
+ optimistic-repeat-install no-hoist no-lockfile no-optional no-runtime prefer-frozen-lockfile
33
+ resolution-only shamefully-hoist side-effects-cache side-effects-cache-readonly s|silent
34
+ strict-peer-dependencies trust-lockfile use-running-store-server use-store-server
35
+ child-concurrency=i hoist-pattern=q lockfile-dir=p modules-dir=p network-concurrency=i
36
+ package-import-method=b public-hoist-pattern=q reporter=b trust-policy=b trust-policy-exclude=q
37
+ trust-policy-ignore-after=i].freeze,
34
38
  install_a: %w[dangerously-allow-all-builds global-dir ignore-scripts offline prefer-offline store-dir=p
35
39
  virtual-store-dir=p].freeze,
36
40
  install_b: %w[D|dev no-optional P|prod].freeze,
37
- add: %w[allow-build config g|global save-catalog D|save-dev O|save-optional save-peer P|save-prod
41
+ add: %w[allow-build config g|global registry=q save-catalog D|save-dev O|save-optional save-peer P|save-prod
38
42
  save-catalog-name=b].freeze,
39
43
  update: %w[g|global i|interactive L|latest depth=i].freeze,
40
44
  dedupe: %w[check].freeze,
@@ -153,10 +157,10 @@ module Squared
153
157
  end
154
158
 
155
159
  subtasks({
156
- 'package' => %i[install add update dedupe rebuild reinstall].freeze,
160
+ 'package' => %i[install add update dedupe approve deny rebuild reinstall].freeze,
157
161
  'outdated' => %i[major minor patch].freeze,
158
162
  'bump' => %i[version major minor patch].freeze,
159
- 'publish' => %i[latest tag].freeze,
163
+ 'publish' => %i[latest tag verify].freeze,
160
164
  'tsc' => %i[project build].freeze,
161
165
  'add' => nil,
162
166
  'run' => nil,
@@ -198,7 +202,7 @@ module Squared
198
202
  when 'add'
199
203
  format_desc action, nil, 'save?=[=-]prod|dev|optional|peer|bundle,(-)name+'
200
204
  task action, [:save] do |_, args|
201
- packages = if args.save =~ /\A([=-]*)?(prod|dev|optional|peer|bundle)\z/
205
+ packages = if args.save =~ /^([=-]*)(prod|dev|optional|peer|bundle)$/
202
206
  save = [$2, $1.include?('='), $1.include?('-')]
203
207
  args.extras
204
208
  else
@@ -209,11 +213,10 @@ module Squared
209
213
  depend(:add, packages: packages, save: save)
210
214
  end
211
215
  when 'run'
212
- next if scripts.empty?
213
-
214
216
  format_desc action, nil, "script,opts*|#{indexchar}index+|#,pattern*"
215
217
  task action, [:script] do |_, args|
216
- list = scripts.to_a
218
+ next if (list = scripts.to_a).empty?
219
+
217
220
  if args.script == '#'
218
221
  format_list(list, "run[#{indexchar}N]", 'scripts', grep: args.extras, from: dependfile)
219
222
  else
@@ -222,7 +225,7 @@ module Squared
222
225
  if (n, extra = indexitem(val))
223
226
  if (item = list[n.pred])
224
227
  run compose([item.first, extra].compact.join(' '), script: true)
225
- elsif exception
228
+ elsif exception?
226
229
  indexerror n, list
227
230
  else
228
231
  log.warn "run script #{n} of #{list.size}".subhint('out of range')
@@ -258,7 +261,7 @@ module Squared
258
261
  list = pnpmopts :exec, :common_filter
259
262
  session 'pnpm', pre.call('r'), pre.call('c'), 'exec'
260
263
  else
261
- list = npmopts :exec
264
+ list = npmopts :exec, :common_scripts
262
265
  session 'npm', 'exec'
263
266
  end
264
267
  op = OptionPartition.new(args, list, cmd, project: self, strict: strict?)
@@ -334,21 +337,34 @@ module Squared
334
337
  end
335
338
  end
336
339
  when 'publish'
337
- format_desc(action, flag, 'otp?,p/ublic|r/estricted?,d/ry-run?', before: ('tag' if flag == :tag))
338
- task flag do |_, args|
339
- args = args.to_a
340
- access = if has_value!(args, 'r', 'restricted')
341
- 'restricted'
342
- elsif has_value!(args, 'p', 'public')
343
- 'public'
344
- end
345
- dryrun = has_value!(args, 'd', 'dry-run')
346
- if flag == :latest
347
- otp = args.first
348
- else
349
- tag, otp = param_guard(action, flag, args: args)
340
+ if flag == :verify
341
+ format_desc action, flag, 'version?,ext*'
342
+ task flag, [:version] do |_, args|
343
+ ext = args.extras
344
+ if (version = args.version)&.match?(/^\.?[a-z]+$/i)
345
+ ext.unshift(version)
346
+ version = nil
347
+ end
348
+ publish(flag, version: version, ext: ext)
349
+ end
350
+ else
351
+ format_desc(action, flag, 'otp?,p/ublic|r/estricted?,d/ry-run?',
352
+ before: ('tag' if flag == :tag))
353
+ task flag do |_, args|
354
+ args = args.to_a
355
+ access = if has_value!(args, 'r', 'restricted')
356
+ 'restricted'
357
+ elsif has_value!(args, 'p', 'public')
358
+ 'public'
359
+ end
360
+ dryrun = has_value!(args, 'd', 'dry-run')
361
+ if flag == :latest
362
+ otp = args.first
363
+ else
364
+ tag, otp = param_guard(action, flag, args: args)
365
+ end
366
+ publish(flag, otp: otp, tag: tag, access: access, dryrun: dryrun)
350
367
  end
351
- publish(flag, otp: otp, tag: tag, access: access, dryrun: dryrun)
352
368
  end
353
369
  when 'tsc'
354
370
  break unless @tsfile
@@ -532,7 +548,6 @@ module Squared
532
548
  end
533
549
  save, exact, omit = save if save.is_a?(Array)
534
550
  ws = env('NODE_WORKSPACES', equals: '0')
535
- ci = option('ci')
536
551
  om = lambda do |cmd|
537
552
  if omit
538
553
  save = case save
@@ -570,7 +585,7 @@ module Squared
570
585
  end
571
586
  if nolockfile?('yarn')
572
587
  cmd << '--no-lockfile'
573
- elsif ci
588
+ elsif option('ci')
574
589
  if yarn == 1
575
590
  cmd << '--frozen-lockfile'
576
591
  elsif !flag
@@ -606,13 +621,27 @@ module Squared
606
621
  '--force'
607
622
  elsif nolockfile?('pnpm')
608
623
  '--no-lockfile'
609
- elsif ci
624
+ elsif option('ci')
610
625
  '--frozen-lockfile'
611
626
  end
612
627
  cmd << '--ignore-scripts' if option('ignore-scripts')
613
628
  cmd << '--dangerously-allow-all-builds' if option('approve-builds')
614
629
  else
615
- cmd = session('npm', ci ? 'ci' : 'install')
630
+ cmd = session 'npm'
631
+ cmd << (ci = option('ci') ? 'ci' : 'install')
632
+ option('approve-scripts') do |val|
633
+ cmd = npm_output 'approve-scripts'
634
+ cmd << case val
635
+ when '1'
636
+ '--all --no-allow-scripts-pin'
637
+ when 'true', 'all'
638
+ '--all'
639
+ else
640
+ val.split(/\s+/).quote!.join(' ')
641
+ end
642
+ print_run cmd, quiet?
643
+ run(cmd, banner: false)
644
+ end
616
645
  cmd << '--workspaces=false' if ws
617
646
  cmd << '--force' if option('force')
618
647
  append_nocolor
@@ -726,7 +755,7 @@ module Squared
726
755
  when :patch
727
756
  a == c && b == d && f[4] != w[4]
728
757
  end
729
- if upgrade && !w[5]
758
+ if upgrade && !w[6]
730
759
  next if file == want
731
760
 
732
761
  found << [key, file, want, if a != c
@@ -882,54 +911,130 @@ module Squared
882
911
  package(:update, from: :update)
883
912
  end
884
913
 
885
- def publish(flag = nil, *, sync: invoked_sync?('publish', flag), otp: nil, tag: nil, access: nil, dryrun: nil)
914
+ def publish(flag = nil, *, sync: invoked_sync?('publish', flag), otp: nil, tag: nil, access: nil, dryrun: nil,
915
+ version: nil, ext: [], workspace: false)
886
916
  if read_package('private')
917
+ return if workspace
918
+
887
919
  ws = children.select { |proj| proj.ref?(Node.ref) }
888
920
  if ws.empty?
889
921
  print_error('nothing to publish', subject: name, hint: 'private')
890
- elsif confirm_basic('Publish workspace?', ws.map(&:name).join(', '), 'N')
891
- ws.each { |proj| proj.publish(flag, sync: sync, otp: otp, tag: tag, access: access, dryrun: dryrun) }
922
+ elsif confirm_basic("#{flag == :verify ? 'Verify' : 'Publish'} workspace?", ws.map(&:name).join(', '), 'N')
923
+ ws.each do |proj|
924
+ proj.publish(flag, sync: sync, otp: otp, tag: tag, access: access, dryrun: dryrun, version: version,
925
+ ext: ext, workspace: true)
926
+ end
892
927
  end
893
- return
894
- end
895
- return print_error("version: #{dependname}", subject: name, hint: 'not found') unless version
896
-
897
- cmd = session 'npm', 'publish'
898
- cmd << basic_option('otp', otp) if otp ||= option('otp')
899
- cmd << basic_option('tag', tag.tr(' ', '-')) if tag ||= option('tag')
900
- case access || option('access')
901
- when 'p', 'public'
902
- cmd << '--access=public'
903
- when 'r', 'restricted'
904
- cmd << '--access=restricted'
905
- end
906
- dryrun ||= dryrun?('npm')
907
- if dryrun
908
- cmd << '--dry-run'
909
- else
910
- from = :'npm:publish'
911
- log.info cmd.to_s
912
- end
913
- if sync
914
- run(sync: sync, from: from, interactive: !dryrun && ['Publish', 'N', npmname])
915
- else
916
- require 'open3'
917
- on :first, from
918
- pwd_set(cmd, dryrun: dryrun) do
919
- cmd = session_done cmd
920
- Open3.popen2e(cmd) do |_, out|
921
- write_lines(out, banner: format_banner(cmd),
922
- sub: npmnotice(opt_style(color(:bright_blue), /^(.+)(Tarball .+)$/, 2)))
928
+ elsif version ||= self.version
929
+ if flag == :verify
930
+ require 'open-uri'
931
+ require 'digest'
932
+ ext = ext.map { |val| val[0] == '.' ? val : ".#{val}" }
933
+ url = "https://unpkg.com/#{read_package('name')}@#{version}?meta"
934
+ print_item format_banner(url, command: false)
935
+ URI.open(url) do |f|
936
+ doc = JSON.parse(f.read)
937
+ n = doc['prefix'].size
938
+ i = 0
939
+ j = doc['files'].size
940
+ pad = j.to_s.size
941
+ m = 0
942
+ c = 0
943
+ e = 0
944
+ doc['files'].each do |item|
945
+ path = item['path'][n..-1]
946
+ js = File.extname(path)
947
+ next unless ext.empty? || ext.any? { |val| val == js }
948
+
949
+ begin
950
+ raise unless (file = basepath!(path)) && item['integrity'] =~ /^(sha\d+)-(.+)$/
951
+
952
+ hash = case $1
953
+ when 'sha384'
954
+ Digest::SHA384
955
+ when 'sha512'
956
+ Digest::SHA512
957
+ else
958
+ Digest::SHA256
959
+ end
960
+ .base64digest(file.read)
961
+ status = if hash == $2
962
+ m += 1
963
+ sub_style 'match', color(:green)
964
+ else
965
+ c += 1
966
+ sub_style 'check', theme[:caution]
967
+ end
968
+ rescue
969
+ status = sub_style 'error', theme[:warn]
970
+ e += 1
971
+ end
972
+ i += 1
973
+ puts "#{i.to_s.rjust(pad)}. #{status} #{path}"
974
+ end
975
+ if i == 0
976
+ puts("No files #{ext.empty? ? 'found' : "matched: #{ext.join(', ')}"}")
977
+ else
978
+ total = ["match #{m}"]
979
+ total << "check #{c}" unless c == 0
980
+ total << "error #{e}" unless e == 0
981
+ unless i == j
982
+ s = "in #{j}"
983
+ if total.size == 1
984
+ total[0] += " #{s}"
985
+ else
986
+ total << s
987
+ end
988
+ end
989
+ puts print_footer(total.join(' / '), right: true, sub: [
990
+ opt_style(color(:green), /^(.*)(match)(.+)$/, 2),
991
+ opt_style(theme[:caution], /^(.+)(check)(.+)$/, 2),
992
+ opt_style(theme[:warn], /^(.+)(error)(.+)$/, 2)
993
+ ])
994
+ end
995
+ end
996
+ else
997
+ cmd = session 'npm', 'publish'
998
+ cmd << basic_option('otp', otp) if otp ||= option('otp')
999
+ cmd << basic_option('tag', tag.tr(' ', '-')) if tag ||= option('tag')
1000
+ case access || option('access')
1001
+ when 'p', 'public'
1002
+ cmd << '--access=public'
1003
+ when 'r', 'restricted'
1004
+ cmd << '--access=restricted'
1005
+ end
1006
+ dryrun ||= dryrun?('npm')
1007
+ if dryrun
1008
+ cmd << '--dry-run'
1009
+ else
1010
+ from = :'npm:publish'
1011
+ log.info cmd.to_s
1012
+ end
1013
+ if sync
1014
+ run(sync: sync, from: from, interactive: !dryrun && ['Publish', 'N', npmname])
1015
+ else
1016
+ require 'open3'
1017
+ on :first, from
1018
+ pwd_set(cmd, dryrun: dryrun) do
1019
+ cmd = session_done cmd
1020
+ Open3.popen2e(cmd) do |_, out|
1021
+ write_lines(out, banner: format_banner(cmd),
1022
+ sub: npmnotice(opt_style(color(:bright_blue), /^(.+)(Tarball .+)$/, 2)))
1023
+ end
1024
+ end
1025
+ on :last, from
923
1026
  end
924
1027
  end
925
- on :last, from
1028
+ elsif !workspace
1029
+ print_error("version: #{dependname}", subject: name, hint: 'not found')
926
1030
  end
927
1031
  end
928
1032
 
929
1033
  def package(flag, opts = [], packages: [], from: nil)
930
1034
  workspace.rev_clear(name)
931
1035
  yarn = dependtype(:yarn)
932
- if yarn > 0 && !(yarn == 1 && ((flag == :update && !packages.empty?) || flag == :rebuild))
1036
+ if yarn > 0 && !(yarn == 1 && ((flag == :update && !packages.empty?) || %i[approve deny
1037
+ rebuild].include?(flag)))
933
1038
  cmd = session 'yarn', case flag
934
1039
  when :update
935
1040
  if yarn == 1
@@ -965,66 +1070,77 @@ module Squared
965
1070
  op << '--ignore-engines' if option('ignore-engines')
966
1071
  end
967
1072
  else
1073
+ flags = []
968
1074
  args = if pnpm?
969
- case flag
970
- when :install, :update
971
- opts << 'no-lockfile' if nolockfile?('pnpm')
972
- spec = 0 if flag == :update
973
- when :add
974
- spec = 1
975
- when :reinstall
976
- opts << 'force'
977
- flag = :install
978
- end
979
- flags = [flag]
980
- flags << :install_a unless flag == :rebuild
981
- unless flag == :dedupe
982
- flags << :common_filter
983
- unless flag == :add
984
- flags << :install_b
985
- flags << :common_cpu unless flag == :update
1075
+ if flag == :approve || flag == :deny
1076
+ opts.map! { |val| val.start_with?('!') ? val : "!#{val}" } if flag == :deny
1077
+ flag = :'approve-builds'
1078
+ spec = true
1079
+ else
1080
+ case flag
1081
+ when :install, :update
1082
+ opts << 'no-lockfile' if nolockfile?('pnpm')
1083
+ spec = 0 if flag == :update
1084
+ when :add
1085
+ spec = 1
1086
+ when :reinstall
1087
+ opts << 'force'
1088
+ flag = :install
986
1089
  end
1090
+ flags << :install_a unless flag == :rebuild
1091
+ unless flag == :dedupe
1092
+ flags << :common_filter
1093
+ unless flag == :add
1094
+ flags << :install_b
1095
+ flags << :common_cpu unless flag == :update
1096
+ end
1097
+ end
1098
+ no = OPT_PNPM[:no][flag]
987
1099
  end
988
- no = OPT_PNPM[:no][flag]
989
1100
  [
990
1101
  opts,
991
- pnpmopts(*flags),
1102
+ pnpmopts(flag, *flags),
992
1103
  session('pnpm', flag)
993
1104
  ]
994
1105
  else
995
- case flag
996
- when :install, :update
997
- opts.unshift('package-lock=false', 'save=false') if nolockfile?('npm')
998
- spec = flag == :install ? 0 : 2
999
- when :add
1000
- spec = 1
1001
- flag = :install
1002
- when :reinstall
1003
- remove_modules 'npm' if opts.delete('force')
1004
- opts.unshift('package-lock=false') if lockfile(true)
1005
- flag = :install
1006
- end
1007
- flags = [flag]
1008
- unless flag == :rebuild
1009
- flags << :install_a
1010
- unless flag == :dedupe
1011
- %w[save ignore-scripts strict-peer-deps].each do |key|
1012
- option(key, prefix: 'npm', ignore: false) do |val|
1013
- opts << basic_option(key, case val
1014
- when '0', 'false'
1015
- false
1016
- else
1017
- true
1018
- end)
1106
+ if flag == :approve || flag == :deny
1107
+ flag = :"#{flag}-scripts"
1108
+ spec = true
1109
+ else
1110
+ case flag
1111
+ when :install, :update
1112
+ opts.unshift('package-lock=false', 'save=false') if nolockfile?('npm')
1113
+ spec = flag == :install ? 0 : 2
1114
+ when :add
1115
+ spec = 1
1116
+ flag = :install
1117
+ when :reinstall
1118
+ remove_modules 'npm' if opts.delete('force')
1119
+ opts.unshift('package-lock=false') if lockfile(true)
1120
+ flag = :install
1121
+ end
1122
+ unless flag == :rebuild
1123
+ flags << :install_a
1124
+ unless flag == :dedupe
1125
+ %w[save ignore-scripts strict-peer-deps].each do |key|
1126
+ option(key, prefix: 'npm', ignore: false) do |val|
1127
+ opts << basic_option(key, case val
1128
+ when '0', 'false'
1129
+ false
1130
+ else
1131
+ true
1132
+ end)
1133
+ end
1019
1134
  end
1135
+ flags << :install_b << :common_scripts
1020
1136
  end
1021
- flags << :install_b
1137
+ flags << :install_c unless flag == :update
1138
+ no = OPT_NPM[:no][:install]
1022
1139
  end
1023
- no = OPT_NPM[:no][:install]
1024
1140
  end
1025
1141
  [
1026
1142
  opts,
1027
- npmopts(*flags),
1143
+ npmopts(flag, *flags),
1028
1144
  session('npm', flag)
1029
1145
  ]
1030
1146
  end
@@ -1052,6 +1168,8 @@ module Squared
1052
1168
 
1053
1169
  op.append(quote: true)
1054
1170
  .clear(errors: true)
1171
+ when true
1172
+ op.append(quote: true)
1055
1173
  else
1056
1174
  op.clear
1057
1175
  end
@@ -1293,6 +1411,10 @@ module Squared
1293
1411
 
1294
1412
  private
1295
1413
 
1414
+ def npm_output(*cmd, **kwargs)
1415
+ session_output('npm', *cmd, **kwargs)
1416
+ end
1417
+
1296
1418
  def read_package(key = 'packageManager', update: false)
1297
1419
  unless !update && @pm.key?(key)
1298
1420
  doc = JSON.parse(dependfile.read)
@@ -201,7 +201,7 @@ module Squared
201
201
  end
202
202
  found |= 1
203
203
  run(script, from: :run)
204
- elsif exception
204
+ elsif exception?
205
205
  indexerror n, list
206
206
  else
207
207
  found |= 2
@@ -216,7 +216,7 @@ module Squared
216
216
  found |= 1
217
217
  run(pdm_session('run', val), from: :run)
218
218
  else
219
- raise "script: #{val}" if exception
219
+ raise "script: #{val}" if exception?
220
220
 
221
221
  found |= 2
222
222
  log.warn "run script \"#{val}\"".subhint('not indexed')
@@ -228,7 +228,7 @@ module Squared
228
228
  end
229
229
  next if found.anybits?(1)
230
230
 
231
- puts log_message(found == 0 ? Logger::INFO : Logger.WARN,
231
+ puts log_message(found == 0 ? Logger::INFO : Logger::WARN,
232
232
  "no scripts #{found == 0 ? 'found' : 'executed'}",
233
233
  subject: name, hint: pyprojectfile)
234
234
  end
@@ -614,7 +614,7 @@ module Squared
614
614
  op.clear
615
615
  when :user, :upgrade
616
616
  op.concat(packages)
617
- raise_error 'no packages listed', hint: flag if op.empty?
617
+ raise_error ArgumentError, 'no packages listed', hint: flag if op.empty?
618
618
  op << "--#{flag}"
619
619
  op.append
620
620
  python_session('-m pip', *op.to_a.drop(1)) if workspace.windows?
@@ -685,6 +685,7 @@ module Squared
685
685
  run(from: from)
686
686
  end
687
687
  end
688
+ alias build_ build!
688
689
 
689
690
  def publish(flag, opts = [], test: false)
690
691
  list = case flag
@@ -771,7 +772,7 @@ module Squared
771
772
  when :install, :uninstall
772
773
  op << '.' if installable? && !op.arg?('r', 'requirement')
773
774
  else
774
- raise_error 'no packages listed', hint: flag
775
+ raise_error ArgumentError, 'no packages listed', hint: flag
775
776
  end
776
777
  elsif flag == :install
777
778
  op.append_any