@pushwoosh/frontend-builder-engine 3.1.1 → 3.1.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.
package/README.md CHANGED
@@ -12,8 +12,33 @@ The CLI is invoked via `pushwoosh-engine` (installed as a dependency in consumin
12
12
  pushwoosh-engine app:command:dev # Start webpack dev server (HTTPS)
13
13
  pushwoosh-engine app:command:build # Production build
14
14
  pushwoosh-engine app:command:analyze # Bundle analysis
15
+ pushwoosh-engine app:command:check-dead-code # Unused files, exports and dependencies (knip)
15
16
  ```
16
17
 
18
+ `app:command:check-dead-code` runs knip with the shipped `lib/knip.application.json`: entries are
19
+ `src/index.{ts,tsx}` plus every `src/parcels/**/index.{ts,tsx}`, so a file the entry graph never
20
+ reaches is reported as unused. Exports used only inside their own file and everything under a
21
+ `generated/` directory are not reported; the binaries and unlisted rules are off, since consuming
22
+ projects get eslint/tsc/webpack from this package rather than declaring them; config hints are
23
+ suppressed, since the config lives here and a consuming project cannot act on them. A project opts
24
+ in by adding the script and folding it into `check`:
25
+
26
+ ```json
27
+ "check": "npm run check:lint && npm run check:types && npm run check:dead-code",
28
+ "check:dead-code": "echo \"Run check:dead-code\" && `pushwoosh-engine app:command:check-dead-code`"
29
+ ```
30
+
31
+ `examples/application` ships with exactly that wiring, so a project copied from the template gets the
32
+ gate on its `pre-commit` hook from the first commit.
33
+
34
+ CI is a separate step: the shared `frontend/microfrontend-release.yml` pipeline runs `check:lint` and
35
+ `check:types` as their own jobs and never calls `npm run check`, so the script alone gates the
36
+ pre-commit hook only. Blocking a merge needs a `check:dead-code` job next to those two.
37
+
38
+ A project whose parcel entry sits outside the globs above (a file no other entry re-exports) needs
39
+ its own `knip.json` in the project root and a plain `knip` call — the shared config is passed with
40
+ `--config` and cannot be extended per project.
41
+
17
42
  ### Library commands (reusable packages)
18
43
 
19
44
  ```bash
@@ -0,0 +1,19 @@
1
+ {
2
+ "$schema": "https://unpkg.com/knip@6/schema.json",
3
+ "entry": [
4
+ "src/index.{ts,tsx}",
5
+ "src/parcels/**/index.{ts,tsx}"
6
+ ],
7
+ "project": [
8
+ "src/**/*.{ts,tsx}"
9
+ ],
10
+ "ignore": [
11
+ "**/generated/**"
12
+ ],
13
+ "ignoreExportsUsedInFile": true,
14
+ "includeEntryExports": false,
15
+ "rules": {
16
+ "binaries": "off",
17
+ "unlisted": "off"
18
+ }
19
+ }
@@ -1,4 +1,5 @@
1
1
  const childProcess = require('child_process');
2
+ const { existsSync, readFileSync } = require('fs');
2
3
  const fs = require('fs').promises;
3
4
  const { program, Command } = require('commander');
4
5
  const path = require('path');
@@ -8,6 +9,28 @@ const { buildStyledComponents } = require('./build-babel');
8
9
  const { loadTsConfig } = require('./lib-build-tsconfig');
9
10
  const { loadPushwooshConfig, listFilesInDirectoryRecursively } = require('./helpers');
10
11
 
12
+ // Printed commands are resolved from the engine's own dependencies, so a project gets no
13
+ // webpack/knip of its own in node_modules/.bin (pnpm does not hoist them).
14
+ const packageDir = (name) => {
15
+ let dir = path.dirname(require.resolve(name));
16
+ for (;;) {
17
+ const manifest = path.join(dir, 'package.json');
18
+ if (existsSync(manifest) && JSON.parse(readFileSync(manifest, 'utf8')).name === name) {
19
+ return dir;
20
+ }
21
+ dir = path.dirname(dir);
22
+ }
23
+ };
24
+
25
+ const bin = (name, command = name) => {
26
+ const dir = packageDir(name);
27
+ const manifest = JSON.parse(readFileSync(path.join(dir, 'package.json'), 'utf8'));
28
+ const entry = typeof manifest.bin === 'string' ? manifest.bin : manifest.bin[command];
29
+ return `node ${path.join(dir, entry)}`;
30
+ };
31
+
32
+ const engineFile = (file) => path.join(__dirname, file);
33
+
11
34
  program
12
35
  .version('1.0.0')
13
36
  .description('Build lib')
@@ -55,9 +78,9 @@ program
55
78
  .description('Playground command')
56
79
  .action(async () => {
57
80
  const cmd = [
58
- './node_modules/.bin/webpack-dev-server',
81
+ bin('webpack-dev-server'),
59
82
  '--config',
60
- './node_modules/@pushwoosh/frontend-builder-engine/lib/webpack.playground.config.js',
83
+ engineFile('webpack.playground.config.js'),
61
84
  '--stats-error-details',
62
85
  ];
63
86
  console.log(cmd.join(' '));
@@ -87,10 +110,10 @@ program
87
110
  .description('App dev command')
88
111
  .action(async () => {
89
112
  const cmd = [
90
- './node_modules/.bin/webpack',
113
+ bin('webpack-cli'),
91
114
  'serve',
92
115
  '--config',
93
- './node_modules/@pushwoosh/frontend-builder-engine/lib/webpack.application.config.js',
116
+ engineFile('webpack.application.config.js'),
94
117
  ];
95
118
  console.log(cmd.join(' '));
96
119
  }),
@@ -102,9 +125,9 @@ program
102
125
  .description('App build command')
103
126
  .action(async () => {
104
127
  const cmd = [
105
- './node_modules/.bin/webpack',
128
+ bin('webpack-cli'),
106
129
  '--config',
107
- './node_modules/@pushwoosh/frontend-builder-engine/lib/webpack.application.config.js',
130
+ engineFile('webpack.application.config.js'),
108
131
  '--stats-error-details',
109
132
  '--mode=production'
110
133
  ];
@@ -112,15 +135,30 @@ program
112
135
  }),
113
136
  );
114
137
 
138
+ program
139
+ .addCommand(
140
+ new Command('app:command:check-dead-code')
141
+ .description('App dead code check command')
142
+ .action(async () => {
143
+ const cmd = [
144
+ bin('knip'),
145
+ '--config',
146
+ engineFile('knip.application.json'),
147
+ '--no-config-hints',
148
+ ];
149
+ console.log(cmd.join(' '));
150
+ }),
151
+ );
152
+
115
153
  program
116
154
  .addCommand(
117
155
  new Command('app:command:analyze')
118
156
  .description('App analyze command')
119
157
  .action(async () => {
120
158
  const cmd = [
121
- './node_modules/.bin/webpack',
159
+ bin('webpack-cli'),
122
160
  '--config',
123
- './node_modules/@pushwoosh/frontend-builder-engine/lib/webpack.application.config.js',
161
+ engineFile('webpack.application.config.js'),
124
162
  '--mode=production',
125
163
  '--env',
126
164
  'analyze',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushwoosh/frontend-builder-engine",
3
- "version": "3.1.1",
3
+ "version": "3.1.3",
4
4
  "description": "Pushwoosh frontend builder engine",
5
5
  "main": "./lib/pushwoosh-frontend-builder-engine.js",
6
6
  "publishConfig": {
@@ -44,6 +44,7 @@
44
44
  "eslint-plugin-react-hooks": "^7.0.1",
45
45
  "fork-ts-checker-webpack-plugin": "^9.0.2",
46
46
  "html-webpack-plugin": "^5.6.0",
47
+ "knip": "^6.35.1",
47
48
  "style-loader": "^4.0.0",
48
49
  "systemjs-webpack-interop": "^2.3.7",
49
50
  "ts-loader": "^9.5.1",