guess-js-deps-bash 0.1.62 → 0.1.64

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.
@@ -24,6 +24,7 @@ local AUTOGUESS_BUILD_UTIL_CMDS=(
24
24
  libdir-binlinks-cfg-linker-pmb
25
25
  npm-ci-utils-pmb
26
26
  uglifyjs
27
+ webpack
27
28
  yamllint
28
29
  yaml-lint-all-recursive
29
30
 
package/guess-js-deps.sh CHANGED
@@ -21,18 +21,16 @@ function guess_js_deps () {
21
21
  devDep
22
22
  peerDep
23
23
  )
24
+ local -A CFG=(
25
+ [runmode]='cmp'
26
+ )
27
+ local POS_ARGN=( runmode )
28
+ local POS_ARGS=()
29
+ parse_cli_opts "$@" || return $?
24
30
 
25
- local RUNMODE="$1"; shift
26
- case "$RUNMODE" in
27
- '..' | '../'* )
28
- cd -- "$RUNMODE" # probably to where your package.json is.
29
- RUNMODE="$1"
30
- shift;;
31
- esac
32
31
  local OUTPUT_MODE=( fail 'Unsupported output mode. This is a bug.' )
33
- case "$RUNMODE" in
32
+ case "${CFG[runmode]}" in
34
33
  as-json ) OUTPUT_MODE=( dump_deps_as_json );;
35
- '' | \
36
34
  cmp ) OUTPUT_MODE=( maybe_colorize_diff compare_deps_as_json );;
37
35
  upd ) OUTPUT_MODE=( update_manifest );;
38
36
  sym ) OUTPUT_MODE=( symlink_nonlocal_node_modules );;
@@ -56,13 +54,46 @@ function guess_js_deps () {
56
54
  tabulate-found ) OUTPUT_MODE=( 'fmt://tsv' );;
57
55
  tabulate-known ) tabulate_manifest_deps; return $?;;
58
56
  --func ) "$@"; return $?;;
59
- * ) fail "unsupported runmode: $RUNMODE"; return 2;;
57
+ * ) fail "unsupported runmode: ${CFG[runmode]}"; return 2;;
60
58
  esac
61
59
 
62
60
  find_imports_in_project "${OUTPUT_MODE[@]}"
63
61
  }
64
62
 
65
63
 
64
+ function parse_cli_opts () {
65
+ local OPT=
66
+ while [ "$#" -gt 0 ]; do
67
+ OPT="$1"; shift
68
+ # [ -n "$OPT" ] || continue
69
+ #case "${CFG[no-more-opts]}$OPT" in
70
+ case "$OPT" in
71
+ '' ) continue;;
72
+ '..' | '../'* ) cd -- "$OPT";; # probably to where your package.json is.
73
+ -- ) POS_ARGS+=( "$@" ); break;;
74
+ #-- ) CFG[no-more-opts]='%%--'; continue;;
75
+ --expect-no-changes | \
76
+ --maybe-no-imports | \
77
+ '' ) CFG["${OPT#--}"]=+;;
78
+ --*=* )
79
+ OPT="${OPT#--}"
80
+ CFG["${OPT%%=*}"]="${OPT#*=}";;
81
+ --help | \
82
+ -* )
83
+ local -fp "${FUNCNAME[0]}" | guess_bash_script_config_opts-pmb
84
+ [ "${OPT//-/}" == help ] && return 1
85
+ echo "E: $0, CLI: unsupported option: $OPT" >&2; return 1;;
86
+ * )
87
+ case "${POS_ARGN[0]}" in
88
+ '' ) echo "E: $0: unexpected positional argument" >&2; return 1;;
89
+ '+' ) POS_ARGS+=( "$OPT" );;
90
+ * ) CFG["${POS_ARGN[0]}"]="$OPT"; POS_ARGN=( "${POS_ARGN[@]:1}" );;
91
+ esac;;
92
+ esac
93
+ done
94
+ }
95
+
96
+
66
97
  function warn_no_args () {
67
98
  [ "$#" -ge 2 ] || echo "W: Calling $1 with no arguments!" >&2
68
99
  "$@"; return $?
@@ -70,8 +101,18 @@ function warn_no_args () {
70
101
 
71
102
 
72
103
  function maybe_colorize_diff () {
73
- [ -z "$*" ] || exec < <("$@")
74
- "${COLORIZE_DIFF:-cat}"
104
+ [ -n "$*" ] || return 0
105
+ if [ -n "$COLORIZE_DIFF" ]; then
106
+ exec > >("$COLORIZE_DIFF")
107
+ fi
108
+ local RV=
109
+ "$@"; RV=$?
110
+
111
+ # Wait for output to go through the coloring process before returning
112
+ # control to parent process. (Which might want to print something
113
+ # immediately, which might overlap.)
114
+ [ -z "$COLORIZE_DIFF" ] || sleep 0.2s
115
+ return "$RV"
75
116
  }
76
117
 
77
118
 
@@ -106,7 +147,7 @@ function init_resolve_cache () {
106
147
 
107
148
 
108
149
  function init_resolve_cache__prep () {
109
- init_resolve_cache__webpack_cfg || return $?
150
+ init_resolve_cache__webpack_cfg eval || return $?
110
151
  init_resolve_cache__forced_custom || return $?
111
152
  }
112
153
 
@@ -114,9 +155,17 @@ function init_resolve_cache__prep () {
114
155
  function init_resolve_cache__webpack_cfg () {
115
156
  local WPCFG='./webpack.config.js'
116
157
  [ -f "$WPCFG" ] || return 0
117
- local VAL="$(nodejs -p "Object.keys(require('$WPCFG'
118
- ).resolve.alias).join('\n')" 2>/dev/null)"
119
- [ -z "$VAL" ] || RESOLVE_CACHE['?packer/alias_pkgnames']+="$VAL"$'\n'
158
+ local SCAN="$SELFPATH"/scan_webpack_config.js
159
+ local LEARN='
160
+ const scan = require(process.env.SCAN);
161
+ const wpcfg = require(process.env.WPCFG);
162
+ JSON.stringify(scan(wpcfg), null, 2)
163
+ '
164
+ LEARN="$(WPCFG="$WPCFG" SCAN="$SCAN" nodejs -e "$LEARN")" || return $?$(
165
+ echo "E: $FUNCNAME: Failed to scan $WPCFG" >&2)
166
+ local NEXT="${1:-echo}"; shift
167
+ "$NEXT" "$@" "$LEARN" || return $?$(
168
+ echo "E: $FUNCNAME: Failed to '$NEXT' the scan report" >&2)
120
169
  }
121
170
 
122
171
 
@@ -165,6 +214,8 @@ function scan_all_scannable_files_in_project () {
165
214
  progress "found ${#IMPORTS[@]}"
166
215
 
167
216
  progress 'I: Searching for require()s/imports: '
217
+ eval "$(init_resolve_cache)"
218
+ find_webpack_config_cached_deps
168
219
  find_imports_in_files "${IMPORTS[@]}"
169
220
  find_manif_script_deps
170
221
  find_manif_eslint_deps
@@ -172,6 +223,12 @@ function scan_all_scannable_files_in_project () {
172
223
  }
173
224
 
174
225
 
226
+ function find_webpack_config_cached_deps () {
227
+ local KEY='bundler://webpack/config/needs'
228
+ <<<"${RESOLVE_CACHE["?$KEY"]}" grep -oPe '\S+' | sed -re 's~$~\t'"$KEY~"
229
+ }
230
+
231
+
175
232
  function find_imports_in_project () {
176
233
  local THEN=( "$@" )
177
234
  local CWD_PKG_NAME="$(guess_cwd_pkg_name)"
@@ -184,8 +241,16 @@ function find_imports_in_project () {
184
241
  | guess_unique_stdin_dep_types 1-3)
185
242
  progress 'done.'
186
243
 
187
- [ -n "${IMPORTS[0]}" ] || return 3$(
188
- fail "Unable to find any import()s/imports in package: $CWD_PKG_NAME")
244
+ local ERR=
245
+ if [ -z "${IMPORTS[0]}" ]; then
246
+ ERR="Unable to find any import()s/imports in package: $CWD_PKG_NAME"
247
+ if [ -n "${CFG[maybe-no-imports]}" ]; then
248
+ echo "D: $ERR"
249
+ return 0
250
+ fi
251
+ fail "$ERR"
252
+ return 3
253
+ fi
189
254
 
190
255
  if [ "${OUTPUT_MODE[0]}" == 'fmt://tsv' ]; then
191
256
  printf '%s\n' "${IMPORTS[@]}"
@@ -238,6 +303,7 @@ function find_manif_eslint_deps () {
238
303
 
239
304
  local ECNP='eslint-config-nodejs-pmb'
240
305
  case "$BUF" in
306
+ *"¶ eslint-config-jslint-compat-pmb "* | \
241
307
  *"¶ $ECNP "* )
242
308
  local PEER_DEPS="$ECNP/test/expectedPeerDependencies.js"
243
309
  PEER_DEPS="require('$PEER_DEPS').join('\n')"
@@ -345,9 +411,15 @@ function compare_deps_as_json () {
345
411
  eval local -A DEP_OFFSETS="( $(find_dep_keys_line_numbers) )"
346
412
 
347
413
  local DEP_TYPE=
414
+ local CHANGES_IN_DEP_TYPES=
415
+
348
416
  for DEP_TYPE in "${KNOWN_DEP_TYPES[@]}"; do
349
417
  compare_deps_as_json__one_dep_type || return $?
350
418
  done
419
+
420
+ [ -z "$CHANGES_IN_DEP_TYPES" ] \
421
+ || [ -z "${CFG[expect-no-changes]}" ] || return 4$(
422
+ fail "Found unexpected changes! in:$CHANGES_IN_DEP_TYPES")
351
423
  }
352
424
 
353
425
 
@@ -359,6 +431,7 @@ function compare_deps_as_json__one_dep_type () {
359
431
  echo "D: no changes in ${DEP_TYPE}s"
360
432
  return 0
361
433
  fi
434
+ CHANGES_IN_DEP_TYPES+=" $DEP_TYPE"
362
435
 
363
436
  local EMPTY="${DEP_OFFSETS[$DEP_TYPE:empty]}"
364
437
  if [ -n "$VERBATIM_EMPTY_ORIG" -a -n "$EMPTY" ]; then
@@ -567,7 +640,6 @@ function find_imports_in_files () {
567
640
  [ "$#" == 0 ] && return 0
568
641
  eval "$(init_resolve_cache)"
569
642
  local SBC_RGX='($bogus^'"$(printf '|%s' "${AUTOGUESS_SHEBANG_CMDS[@]}"))"
570
-
571
643
  LANG=C grep -PHone '#!.*$|^(\xEF\xBB\xBF|)\s*'$(
572
644
  )'(import|\W*from)\s.*$|require\([^()]+\)' -- "$@" \
573
645
  | tr "'" '"' | LANG=C sed -rf <(echo '
@@ -692,9 +764,9 @@ function guess_one_dep_type () {
692
764
  esac
693
765
 
694
766
  if [ -z "$DEP_VER" ]; then
695
- case $'\n'"${RESOLVE_CACHE['?packer/alias_pkgnames']}"$'\n' in
696
- *$'\n'"${REQ_MOD%%/*}"$'\n'* )
697
- DEP_TYPE='packer-alias'
767
+ case " ${RESOLVE_CACHE['?bundler://alias_pkgnames']} " in
768
+ *" ${REQ_MOD%%/*} "* )
769
+ DEP_TYPE='bundler-alias'
698
770
  DEP_VER='*';;
699
771
  esac
700
772
  fi
@@ -751,9 +823,10 @@ function guess_one_dep_type () {
751
823
  esac
752
824
 
753
825
  case "$REQ_NORM_FEXT" in
826
+ bundler://* | \
827
+ manif://lint | \
754
828
  manif://scripts/*lint* | \
755
829
  manif://scripts/*test* | \
756
- manif://lint | \
757
830
  . ) DEP_TYPE=devDep;;
758
831
  */* ) ;; # files in subdirs are handled above
759
832
  # below: top-level files
@@ -4,3 +4,4 @@
4
4
  s~^(demo-util-160404)-test-demos(\t)~lib-\1\2~
5
5
  s~^(uglify)(js\t)~\1-\2~
6
6
  s~^(yaml)(lint\t)~\1-\2~
7
+ s~^(webpack)~\1-cli~
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  { "name": "guess-js-deps-bash",
2
- "version": "0.1.62",
2
+ "version": "0.1.64",
3
3
  "description": "A bash attempt at npm-forgot: Guess JavaScript require() dependencies, detect their versions, compare with package.json.",
4
4
 
5
5
  "keywords": [
@@ -26,12 +26,18 @@
26
26
 
27
27
  "main": "capture-bash.js",
28
28
  "bin": { "guess-js-deps": "guess-js-deps.sh" },
29
- "scripts": { "test": "nodejs test/all.js" },
29
+ "scripts": { "test": "elp && guess-js-deps cmp --expect-no-changes" },
30
30
  "directories": { "test": "test" },
31
+ "eslintConfig": { "extends": "nodejs-pmb" },
31
32
 
32
33
  "dependencies": {},
33
- "devDependencies": {},
34
+ "devDependencies": {
35
+ "eslint-config-nodejs-pmb": "^0.3.5",
36
+ "eslint-plugin-json-light-pmb": "^1.0.7",
37
+ "eslint-plugin-n": "^15.2.4",
38
+ "eslint-pretty-pmb": "^1.0.5"
39
+ },
34
40
 
35
41
 
36
- "npm vs. BOM = Unexpected token": "-*- coding: UTF-8 -*-"
42
+ "engines": { "npm": ">=7.0.0", "node": ">=16.0.0" }
37
43
  }
@@ -0,0 +1,53 @@
1
+ 'use strict';
2
+
3
+ // const same = require('assert').deepStrictEqual;
4
+
5
+ function orf(x) { return x || false; }
6
+ function shellQuoteNoApos(s) { return "'" + s.replace(/'/g, '') + "'"; }
7
+
8
+ function setSlotNoApos(k, v, op) {
9
+ console.log("RESOLVE_CACHE['" + k + "']" + (op || '') + '='
10
+ + shellQuoteNoApos(v));
11
+ }
12
+
13
+
14
+ const EX = function scanWebpackConfig(wpCfg) {
15
+ const scan = {
16
+ wpCfg,
17
+ needPkgs: new Set(EX.alwaysNeededPkgs),
18
+ };
19
+ EX.aliases(scan);
20
+ EX.resourceLoaders(scan);
21
+
22
+ setSlotNoApos('?bundler://webpack/config/needs',
23
+ Array.from(scan.needPkgs.values()).sort().join(' '));
24
+ };
25
+
26
+
27
+ Object.assign(EX, {
28
+
29
+ alwaysNeededPkgs: [
30
+ 'browserslist',
31
+ ],
32
+
33
+
34
+ aliases(scan) {
35
+ const alNames = Object.keys(orf(orf(scan.wpCfg.resolve).alias)).join(' ');
36
+ if (!alNames) { return; }
37
+ setSlotNoApos('?bundler://alias_pkgnames', (' ' + alNames + ' '), '+');
38
+ },
39
+
40
+
41
+ resourceLoaders(scan) {
42
+ [].concat(orf(scan.wpCfg.module).rules).forEach(function foundRule(rule) {
43
+ if (!rule) { return; }
44
+ const ldr = (rule.loader || orf(rule.use).loader);
45
+ if (!ldr) { return; }
46
+ scan.needPkgs.add(ldr);
47
+ });
48
+ },
49
+
50
+
51
+ });
52
+
53
+ module.exports = EX;