shakapacker 9.3.0.beta.6 → 9.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +46 -105
- data/ESLINT_TECHNICAL_DEBT.md +8 -2
- data/Gemfile.lock +1 -1
- data/README.md +53 -2
- data/docs/configuration.md +28 -0
- data/docs/rspack_migration_guide.md +238 -2
- data/docs/troubleshooting.md +21 -21
- data/eslint.config.fast.js +8 -0
- data/eslint.config.js +47 -10
- data/knip.ts +8 -1
- data/lib/install/config/shakapacker.yml +6 -6
- data/lib/shakapacker/configuration.rb +227 -4
- data/lib/shakapacker/dev_server.rb +88 -1
- data/lib/shakapacker/doctor.rb +129 -72
- data/lib/shakapacker/instance.rb +85 -1
- data/lib/shakapacker/manifest.rb +85 -11
- data/lib/shakapacker/runner.rb +12 -8
- data/lib/shakapacker/swc_migrator.rb +7 -7
- data/lib/shakapacker/version.rb +1 -1
- data/lib/shakapacker.rb +143 -3
- data/lib/tasks/shakapacker/doctor.rake +1 -1
- data/lib/tasks/shakapacker/export_bundler_config.rake +4 -4
- data/package/config.ts +0 -1
- data/package/configExporter/buildValidator.ts +53 -29
- data/package/configExporter/cli.ts +152 -118
- data/package/configExporter/configFile.ts +33 -26
- data/package/configExporter/fileWriter.ts +3 -3
- data/package/configExporter/types.ts +64 -0
- data/package/configExporter/yamlSerializer.ts +147 -36
- data/package/dev_server.ts +2 -1
- data/package/env.ts +1 -1
- data/package/environments/base.ts +4 -4
- data/package/environments/development.ts +7 -6
- data/package/environments/production.ts +6 -7
- data/package/environments/test.ts +2 -1
- data/package/index.ts +28 -4
- data/package/loaders.d.ts +2 -2
- data/package/optimization/webpack.ts +29 -31
- data/package/plugins/webpack.ts +2 -1
- data/package/rspack/index.ts +2 -1
- data/package/rules/file.ts +1 -0
- data/package/rules/jscommon.ts +1 -0
- data/package/utils/helpers.ts +0 -1
- data/package/utils/pathValidation.ts +68 -7
- data/package/utils/requireOrError.ts +10 -2
- data/package/utils/typeGuards.ts +43 -46
- data/package/webpack-types.d.ts +2 -2
- data/package/webpackDevServerConfig.ts +1 -0
- data/package.json +2 -3
- data/test/configExporter/integration.test.js +8 -8
- data/test/package/configExporter/cli.test.js +440 -0
- data/test/package/configExporter/types.test.js +163 -0
- data/test/package/configExporter.test.js +271 -7
- data/test/package/yamlSerializer.test.js +204 -0
- data/test/typescript/pathValidation.test.js +44 -0
- data/test/typescript/requireOrError.test.js +49 -0
- data/yarn.lock +0 -32
- metadata +11 -6
- data/.eslintrc.fast.js +0 -40
- data/.eslintrc.js +0 -84
- data/package-lock.json +0 -13047
data/lib/shakapacker.rb
CHANGED
|
@@ -3,22 +3,86 @@ require "active_support/core_ext/string/inquiry"
|
|
|
3
3
|
require "active_support/logger"
|
|
4
4
|
require "active_support/tagged_logging"
|
|
5
5
|
|
|
6
|
+
# = Shakapacker
|
|
7
|
+
#
|
|
8
|
+
# Shakapacker is a Ruby gem that integrates webpack and rspack with Rails applications,
|
|
9
|
+
# providing a modern asset pipeline for JavaScript, CSS, and other web assets.
|
|
10
|
+
#
|
|
11
|
+
# The main Shakapacker module provides singleton-style access to configuration,
|
|
12
|
+
# compilation, and asset manifest functionality. Most methods delegate to a shared
|
|
13
|
+
# {Shakapacker::Instance} object.
|
|
14
|
+
#
|
|
15
|
+
# == Basic Usage
|
|
16
|
+
#
|
|
17
|
+
# # Access configuration
|
|
18
|
+
# Shakapacker.config.source_path
|
|
19
|
+
# #=> Pathname("/path/to/app/packs")
|
|
20
|
+
#
|
|
21
|
+
# # Check if dev server is running
|
|
22
|
+
# Shakapacker.dev_server.running?
|
|
23
|
+
# #=> true
|
|
24
|
+
#
|
|
25
|
+
# # Look up compiled assets
|
|
26
|
+
# Shakapacker.manifest.lookup("application.js")
|
|
27
|
+
# #=> "/packs/application-abc123.js"
|
|
28
|
+
#
|
|
29
|
+
# # Compile assets
|
|
30
|
+
# Shakapacker.compile
|
|
31
|
+
#
|
|
32
|
+
# == Configuration
|
|
33
|
+
#
|
|
34
|
+
# Configuration is loaded from +config/shakapacker.yml+ and can be accessed via
|
|
35
|
+
# {Shakapacker.config}. The configuration determines the source paths, output paths,
|
|
36
|
+
# compilation settings, and dev server options.
|
|
37
|
+
#
|
|
38
|
+
# @see Shakapacker::Configuration
|
|
39
|
+
# @see Shakapacker::Instance
|
|
6
40
|
module Shakapacker
|
|
7
41
|
extend self
|
|
8
42
|
|
|
43
|
+
# Default environment when RAILS_ENV is not set
|
|
9
44
|
DEFAULT_ENV = "development".freeze
|
|
10
45
|
# Environments that use their RAILS_ENV value for NODE_ENV
|
|
11
46
|
# All other environments (production, staging, etc.) use "production" for webpack optimizations
|
|
12
47
|
DEV_TEST_ENVS = %w[development test].freeze
|
|
13
48
|
|
|
49
|
+
# Sets the shared Shakapacker instance
|
|
50
|
+
#
|
|
51
|
+
# This is primarily used for testing or advanced customization scenarios.
|
|
52
|
+
# In most applications, the default instance is sufficient.
|
|
53
|
+
#
|
|
54
|
+
# @param instance [Shakapacker::Instance] the instance to use
|
|
55
|
+
# @return [Shakapacker::Instance] the instance that was set
|
|
56
|
+
# @api public
|
|
14
57
|
def instance=(instance)
|
|
15
58
|
@instance = instance
|
|
16
59
|
end
|
|
17
60
|
|
|
61
|
+
# Returns the shared Shakapacker instance
|
|
62
|
+
#
|
|
63
|
+
# This instance is used by all module-level delegate methods. It provides
|
|
64
|
+
# access to configuration, compilation, manifest lookup, and more.
|
|
65
|
+
#
|
|
66
|
+
# @return [Shakapacker::Instance] the shared instance
|
|
67
|
+
# @api public
|
|
18
68
|
def instance
|
|
19
69
|
@instance ||= Shakapacker::Instance.new
|
|
20
70
|
end
|
|
21
71
|
|
|
72
|
+
# Temporarily overrides NODE_ENV for the duration of the block
|
|
73
|
+
#
|
|
74
|
+
# This is useful when you need to perform operations with a specific NODE_ENV
|
|
75
|
+
# value without permanently changing the environment.
|
|
76
|
+
#
|
|
77
|
+
# @param env [String] the NODE_ENV value to use temporarily
|
|
78
|
+
# @yield the block to execute with the temporary NODE_ENV
|
|
79
|
+
# @return [Object] the return value of the block
|
|
80
|
+
# @example
|
|
81
|
+
# Shakapacker.with_node_env("production") do
|
|
82
|
+
# # This code runs with NODE_ENV=production
|
|
83
|
+
# Shakapacker.compile
|
|
84
|
+
# end
|
|
85
|
+
# @api public
|
|
22
86
|
def with_node_env(env)
|
|
23
87
|
original = ENV["NODE_ENV"]
|
|
24
88
|
ENV["NODE_ENV"] = env
|
|
@@ -27,13 +91,32 @@ module Shakapacker
|
|
|
27
91
|
ENV["NODE_ENV"] = original
|
|
28
92
|
end
|
|
29
93
|
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
94
|
+
# Sets NODE_ENV based on RAILS_ENV if not already set
|
|
95
|
+
#
|
|
96
|
+
# Environment mapping:
|
|
97
|
+
# - +development+ and +test+ environments use their RAILS_ENV value for NODE_ENV
|
|
98
|
+
# - All other environments (+production+, +staging+, etc.) use "production" for webpack optimizations
|
|
99
|
+
#
|
|
100
|
+
# This method is typically called automatically during Rails initialization.
|
|
101
|
+
#
|
|
102
|
+
# @return [String] the NODE_ENV value that was set
|
|
103
|
+
# @api private
|
|
33
104
|
def ensure_node_env!
|
|
34
105
|
ENV["NODE_ENV"] ||= DEV_TEST_ENVS.include?(ENV["RAILS_ENV"]) ? ENV["RAILS_ENV"] : "production"
|
|
35
106
|
end
|
|
36
107
|
|
|
108
|
+
# Temporarily redirects Shakapacker logging to STDOUT
|
|
109
|
+
#
|
|
110
|
+
# This is useful for debugging or when you want to see compilation output
|
|
111
|
+
# in the console instead of the Rails log.
|
|
112
|
+
#
|
|
113
|
+
# @yield the block to execute with STDOUT logging
|
|
114
|
+
# @return [Object] the return value of the block
|
|
115
|
+
# @example
|
|
116
|
+
# Shakapacker.ensure_log_goes_to_stdout do
|
|
117
|
+
# Shakapacker.compile
|
|
118
|
+
# end
|
|
119
|
+
# @api public
|
|
37
120
|
def ensure_log_goes_to_stdout
|
|
38
121
|
old_logger = Shakapacker.logger
|
|
39
122
|
Shakapacker.logger = Logger.new(STDOUT)
|
|
@@ -42,8 +125,65 @@ module Shakapacker
|
|
|
42
125
|
Shakapacker.logger = old_logger
|
|
43
126
|
end
|
|
44
127
|
|
|
128
|
+
# @!method logger
|
|
129
|
+
# Returns the logger instance used by Shakapacker
|
|
130
|
+
# @return [Logger] the logger instance
|
|
131
|
+
# @see Shakapacker::Instance#logger
|
|
132
|
+
# @!method logger=(logger)
|
|
133
|
+
# Sets the logger instance used by Shakapacker
|
|
134
|
+
# @param logger [Logger] the logger to use
|
|
135
|
+
# @return [Logger] the logger that was set
|
|
136
|
+
# @see Shakapacker::Instance#logger=
|
|
137
|
+
# @!method env
|
|
138
|
+
# Returns the current Rails environment as an ActiveSupport::StringInquirer
|
|
139
|
+
# @return [ActiveSupport::StringInquirer] the environment
|
|
140
|
+
# @see Shakapacker::Instance#env
|
|
141
|
+
# @!method inlining_css?
|
|
142
|
+
# Returns whether CSS inlining is enabled
|
|
143
|
+
# @return [Boolean] true if CSS should be inlined
|
|
144
|
+
# @see Shakapacker::Instance#inlining_css?
|
|
45
145
|
delegate :logger, :logger=, :env, :inlining_css?, to: :instance
|
|
146
|
+
|
|
147
|
+
# @!method config
|
|
148
|
+
# Returns the Shakapacker configuration object
|
|
149
|
+
# @return [Shakapacker::Configuration] the configuration
|
|
150
|
+
# @see Shakapacker::Instance#config
|
|
151
|
+
# @!method compiler
|
|
152
|
+
# Returns the compiler instance for compiling assets
|
|
153
|
+
# @return [Shakapacker::Compiler] the compiler
|
|
154
|
+
# @see Shakapacker::Instance#compiler
|
|
155
|
+
# @!method manifest
|
|
156
|
+
# Returns the manifest instance for looking up compiled assets
|
|
157
|
+
# @return [Shakapacker::Manifest] the manifest
|
|
158
|
+
# @see Shakapacker::Instance#manifest
|
|
159
|
+
# @!method commands
|
|
160
|
+
# Returns the commands instance for build operations
|
|
161
|
+
# @return [Shakapacker::Commands] the commands object
|
|
162
|
+
# @see Shakapacker::Instance#commands
|
|
163
|
+
# @!method dev_server
|
|
164
|
+
# Returns the dev server instance for querying server status
|
|
165
|
+
# @return [Shakapacker::DevServer] the dev server
|
|
166
|
+
# @see Shakapacker::Instance#dev_server
|
|
46
167
|
delegate :config, :compiler, :manifest, :commands, :dev_server, to: :instance
|
|
168
|
+
|
|
169
|
+
# @!method bootstrap
|
|
170
|
+
# Creates the default configuration files and directory structure
|
|
171
|
+
# @return [void]
|
|
172
|
+
# @see Shakapacker::Commands#bootstrap
|
|
173
|
+
# @!method clean(count = nil, age = nil)
|
|
174
|
+
# Removes old compiled packs, keeping the most recent versions
|
|
175
|
+
# @param count [Integer, nil] number of versions to keep per entry
|
|
176
|
+
# @param age [Integer, nil] maximum age in seconds for packs to keep
|
|
177
|
+
# @return [void]
|
|
178
|
+
# @see Shakapacker::Commands#clean
|
|
179
|
+
# @!method clobber
|
|
180
|
+
# Removes all compiled packs
|
|
181
|
+
# @return [void]
|
|
182
|
+
# @see Shakapacker::Commands#clobber
|
|
183
|
+
# @!method compile
|
|
184
|
+
# Compiles all webpack/rspack packs
|
|
185
|
+
# @return [Boolean] true if compilation succeeded
|
|
186
|
+
# @see Shakapacker::Commands#compile
|
|
47
187
|
delegate :bootstrap, :clean, :clobber, :compile, to: :commands
|
|
48
188
|
end
|
|
49
189
|
|
|
@@ -11,7 +11,7 @@ namespace :shakapacker do
|
|
|
11
11
|
• Required and optional npm dependencies
|
|
12
12
|
• JavaScript transpiler (Babel, SWC, esbuild) configuration
|
|
13
13
|
• CSS, CSS Modules, and stylesheet preprocessor setup
|
|
14
|
-
• Binstubs presence (shakapacker, shakapacker-dev-server,
|
|
14
|
+
• Binstubs presence (shakapacker, shakapacker-dev-server, shakapacker-config)
|
|
15
15
|
• Version consistency between gem and npm package
|
|
16
16
|
• Legacy Webpacker file detection
|
|
17
17
|
|
|
@@ -42,18 +42,18 @@ namespace :shakapacker do
|
|
|
42
42
|
Note: When using 'rake', you must use '--' to separate rake options from task arguments.
|
|
43
43
|
Example: rake shakapacker:export_bundler_config -- --doctor
|
|
44
44
|
|
|
45
|
-
The task automatically falls back to the gem version if bin/
|
|
45
|
+
The task automatically falls back to the gem version if bin/shakapacker-config
|
|
46
46
|
binstub is not installed. To install all binstubs, run: rails shakapacker:binstubs
|
|
47
47
|
DESC
|
|
48
48
|
task :export_bundler_config do
|
|
49
49
|
# Try to use the binstub if it exists, otherwise use the gem's version
|
|
50
|
-
bin_path = Rails.root.join("bin/
|
|
50
|
+
bin_path = Rails.root.join("bin/shakapacker-config")
|
|
51
51
|
|
|
52
52
|
unless File.exist?(bin_path)
|
|
53
53
|
# Binstub not installed, use the gem's version directly
|
|
54
|
-
gem_bin_path = File.expand_path("../../install/bin/
|
|
54
|
+
gem_bin_path = File.expand_path("../../install/bin/shakapacker-config", __dir__)
|
|
55
55
|
|
|
56
|
-
$stderr.puts "Note: bin/
|
|
56
|
+
$stderr.puts "Note: bin/shakapacker-config binstub not found."
|
|
57
57
|
$stderr.puts "Using gem version directly. To install the binstub, run: rake shakapacker:binstubs"
|
|
58
58
|
$stderr.puts ""
|
|
59
59
|
|
data/package/config.ts
CHANGED
|
@@ -55,7 +55,6 @@ if (existsSync(configPath)) {
|
|
|
55
55
|
const envAppConfig = appYmlObject[railsEnv]
|
|
56
56
|
|
|
57
57
|
if (!envAppConfig) {
|
|
58
|
-
/* eslint no-console:0 */
|
|
59
58
|
console.warn(
|
|
60
59
|
`[SHAKAPACKER WARNING] Environment '${railsEnv}' not found in ${configPath}\n` +
|
|
61
60
|
`Available environments: ${Object.keys(appYmlObject).join(", ")}\n` +
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { spawn } from "child_process"
|
|
2
2
|
import { existsSync } from "fs"
|
|
3
|
-
import { resolve, relative
|
|
3
|
+
import { resolve, relative } from "path"
|
|
4
4
|
import { ResolvedBuildConfig, BuildValidationResult } from "./types"
|
|
5
5
|
|
|
6
6
|
export interface ValidatorOptions {
|
|
@@ -173,7 +173,7 @@ export class BuildValidator {
|
|
|
173
173
|
* @returns The resolved absolute path to the config file
|
|
174
174
|
* @throws Error if the config file does not exist or is outside appRoot
|
|
175
175
|
*/
|
|
176
|
-
private validateConfigPath(
|
|
176
|
+
private static validateConfigPath(
|
|
177
177
|
configFile: string,
|
|
178
178
|
appRoot: string,
|
|
179
179
|
buildName: string
|
|
@@ -222,7 +222,7 @@ export class BuildValidator {
|
|
|
222
222
|
const isHMR =
|
|
223
223
|
build.environment.WEBPACK_SERVE === "true" ||
|
|
224
224
|
build.environment.HMR === "true"
|
|
225
|
-
const bundler = build
|
|
225
|
+
const { bundler } = build
|
|
226
226
|
|
|
227
227
|
if (isHMR) {
|
|
228
228
|
return this.validateHMRBuild(build, appRoot, bundler)
|
|
@@ -273,7 +273,7 @@ export class BuildValidator {
|
|
|
273
273
|
// Add config file if specified
|
|
274
274
|
if (build.configFile) {
|
|
275
275
|
try {
|
|
276
|
-
const configPath =
|
|
276
|
+
const configPath = BuildValidator.validateConfigPath(
|
|
277
277
|
build.configFile,
|
|
278
278
|
appRoot,
|
|
279
279
|
build.name
|
|
@@ -301,7 +301,7 @@ export class BuildValidator {
|
|
|
301
301
|
args.push(...build.bundlerEnvArgs)
|
|
302
302
|
}
|
|
303
303
|
|
|
304
|
-
return new Promise((
|
|
304
|
+
return new Promise((resolvePromise) => {
|
|
305
305
|
const child = spawn(devServerBin, args, {
|
|
306
306
|
cwd: appRoot,
|
|
307
307
|
env: this.filterEnvironment(build.environment),
|
|
@@ -316,7 +316,7 @@ export class BuildValidator {
|
|
|
316
316
|
const resolveOnce = (res: BuildValidationResult) => {
|
|
317
317
|
if (!resolved) {
|
|
318
318
|
resolved = true
|
|
319
|
-
|
|
319
|
+
resolvePromise(res)
|
|
320
320
|
}
|
|
321
321
|
}
|
|
322
322
|
|
|
@@ -397,8 +397,8 @@ export class BuildValidator {
|
|
|
397
397
|
})
|
|
398
398
|
}
|
|
399
399
|
|
|
400
|
-
child.stdout?.on("data", (data) => processOutput(data))
|
|
401
|
-
child.stderr?.on("data", (data) => processOutput(data))
|
|
400
|
+
child.stdout?.on("data", (data: Buffer) => processOutput(data))
|
|
401
|
+
child.stderr?.on("data", (data: Buffer) => processOutput(data))
|
|
402
402
|
|
|
403
403
|
child.on("exit", (code) => {
|
|
404
404
|
clearTimeout(timeoutId)
|
|
@@ -428,7 +428,7 @@ export class BuildValidator {
|
|
|
428
428
|
|
|
429
429
|
// Check for specific error codes and provide actionable guidance
|
|
430
430
|
if ("code" in err) {
|
|
431
|
-
const code =
|
|
431
|
+
const { code } = err as NodeJS.ErrnoException
|
|
432
432
|
if (code === "ENOENT") {
|
|
433
433
|
errorMessage += `. Binary not found. Install with: npm install -D ${devServerCmd}`
|
|
434
434
|
} else if (code === "EMFILE" || code === "ENFILE") {
|
|
@@ -484,7 +484,7 @@ export class BuildValidator {
|
|
|
484
484
|
// Add config file if specified
|
|
485
485
|
if (build.configFile) {
|
|
486
486
|
try {
|
|
487
|
-
const configPath =
|
|
487
|
+
const configPath = BuildValidator.validateConfigPath(
|
|
488
488
|
build.configFile,
|
|
489
489
|
appRoot,
|
|
490
490
|
build.name
|
|
@@ -515,7 +515,7 @@ export class BuildValidator {
|
|
|
515
515
|
// Add --json for structured output (helps parse errors)
|
|
516
516
|
args.push("--json")
|
|
517
517
|
|
|
518
|
-
return new Promise((
|
|
518
|
+
return new Promise((resolvePromise) => {
|
|
519
519
|
const child = spawn(bundlerBin, args, {
|
|
520
520
|
cwd: appRoot,
|
|
521
521
|
env: this.filterEnvironment(build.environment),
|
|
@@ -534,7 +534,7 @@ export class BuildValidator {
|
|
|
534
534
|
`Timeout: ${bundler} did not complete within ${this.options.timeout}ms.`
|
|
535
535
|
)
|
|
536
536
|
child.kill("SIGTERM")
|
|
537
|
-
|
|
537
|
+
resolvePromise(result)
|
|
538
538
|
}, this.options.timeout)
|
|
539
539
|
|
|
540
540
|
child.stdout?.on("data", (data: Buffer) => {
|
|
@@ -603,7 +603,7 @@ export class BuildValidator {
|
|
|
603
603
|
|
|
604
604
|
// Parse JSON output
|
|
605
605
|
try {
|
|
606
|
-
const jsonOutput
|
|
606
|
+
const jsonOutput = JSON.parse(stdoutData) as WebpackJsonOutput
|
|
607
607
|
|
|
608
608
|
// Extract output path if available
|
|
609
609
|
if (jsonOutput.outputPath) {
|
|
@@ -613,10 +613,22 @@ export class BuildValidator {
|
|
|
613
613
|
// Check for errors in webpack/rspack JSON output
|
|
614
614
|
if (jsonOutput.errors && jsonOutput.errors.length > 0) {
|
|
615
615
|
jsonOutput.errors.forEach((error) => {
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
616
|
+
let errorMsg: string
|
|
617
|
+
if (typeof error === "string") {
|
|
618
|
+
errorMsg = error
|
|
619
|
+
} else if (error.message) {
|
|
620
|
+
errorMsg = error.message
|
|
621
|
+
} else {
|
|
622
|
+
// Attempt to extract useful info from malformed error using all enumerable props
|
|
623
|
+
try {
|
|
624
|
+
errorMsg = JSON.stringify(
|
|
625
|
+
error,
|
|
626
|
+
Object.getOwnPropertyNames(error)
|
|
627
|
+
)
|
|
628
|
+
} catch {
|
|
629
|
+
errorMsg = "[Error object with no message]"
|
|
630
|
+
}
|
|
631
|
+
}
|
|
620
632
|
result.errors.push(errorMsg)
|
|
621
633
|
// Also add to output for visibility
|
|
622
634
|
if (!this.options.verbose) {
|
|
@@ -628,10 +640,22 @@ export class BuildValidator {
|
|
|
628
640
|
// Check for warnings
|
|
629
641
|
if (jsonOutput.warnings && jsonOutput.warnings.length > 0) {
|
|
630
642
|
jsonOutput.warnings.forEach((warning) => {
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
643
|
+
let warningMsg: string
|
|
644
|
+
if (typeof warning === "string") {
|
|
645
|
+
warningMsg = warning
|
|
646
|
+
} else if (warning.message) {
|
|
647
|
+
warningMsg = warning.message
|
|
648
|
+
} else {
|
|
649
|
+
// Attempt to extract useful info from malformed warning using all enumerable props
|
|
650
|
+
try {
|
|
651
|
+
warningMsg = JSON.stringify(
|
|
652
|
+
warning,
|
|
653
|
+
Object.getOwnPropertyNames(warning)
|
|
654
|
+
)
|
|
655
|
+
} catch {
|
|
656
|
+
warningMsg = "[Warning object with no message]"
|
|
657
|
+
}
|
|
658
|
+
}
|
|
635
659
|
result.warnings.push(warningMsg)
|
|
636
660
|
})
|
|
637
661
|
}
|
|
@@ -683,7 +707,7 @@ export class BuildValidator {
|
|
|
683
707
|
result.output.push(stderrData)
|
|
684
708
|
}
|
|
685
709
|
|
|
686
|
-
|
|
710
|
+
resolvePromise(result)
|
|
687
711
|
})
|
|
688
712
|
|
|
689
713
|
child.on("error", (err) => {
|
|
@@ -693,7 +717,7 @@ export class BuildValidator {
|
|
|
693
717
|
|
|
694
718
|
// Check for specific error codes and provide actionable guidance
|
|
695
719
|
if ("code" in err) {
|
|
696
|
-
const code =
|
|
720
|
+
const { code } = err as NodeJS.ErrnoException
|
|
697
721
|
if (code === "ENOENT") {
|
|
698
722
|
errorMessage += `. Binary not found. Install with: npm install -D ${bundler}`
|
|
699
723
|
} else if (code === "EMFILE" || code === "ENFILE") {
|
|
@@ -704,7 +728,7 @@ export class BuildValidator {
|
|
|
704
728
|
}
|
|
705
729
|
|
|
706
730
|
result.errors.push(errorMessage)
|
|
707
|
-
|
|
731
|
+
resolvePromise(result)
|
|
708
732
|
})
|
|
709
733
|
})
|
|
710
734
|
}
|
|
@@ -776,19 +800,19 @@ export class BuildValidator {
|
|
|
776
800
|
formatResults(results: BuildValidationResult[]): string {
|
|
777
801
|
const lines: string[] = []
|
|
778
802
|
|
|
779
|
-
lines.push(
|
|
803
|
+
lines.push(`\n${"=".repeat(80)}`)
|
|
780
804
|
lines.push("🔍 Build Validation Results")
|
|
781
|
-
lines.push("=".repeat(80)
|
|
805
|
+
lines.push(`${"=".repeat(80)}\n`)
|
|
782
806
|
|
|
783
|
-
|
|
807
|
+
const totalBuilds = results.length
|
|
784
808
|
let successCount = 0
|
|
785
809
|
let failureCount = 0
|
|
786
810
|
|
|
787
811
|
results.forEach((result) => {
|
|
788
812
|
if (result.success) {
|
|
789
|
-
successCount
|
|
813
|
+
successCount += 1
|
|
790
814
|
} else {
|
|
791
|
-
failureCount
|
|
815
|
+
failureCount += 1
|
|
792
816
|
}
|
|
793
817
|
|
|
794
818
|
const icon = result.success ? "✅" : "❌"
|