shakapacker 9.3.0.beta.0 → 9.3.0.beta.2

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.
@@ -10,6 +10,7 @@ import { ExportOptions, ConfigMetadata, FileOutput } from "./types"
10
10
  import { YamlSerializer } from "./yamlSerializer"
11
11
  import { FileWriter } from "./fileWriter"
12
12
  import { ConfigFileLoader, generateSampleConfigFile } from "./configFile"
13
+ import { BuildValidator } from "./buildValidator"
13
14
 
14
15
  // Read version from package.json
15
16
  const packageJson = JSON.parse(
@@ -84,6 +85,11 @@ export async function run(args: string[]): Promise<number> {
84
85
  return runListBuildsCommand(options)
85
86
  }
86
87
 
88
+ // Handle --validate or --validate-build command
89
+ if (options.validate || options.validateBuild) {
90
+ return await runValidateCommand(options)
91
+ }
92
+
87
93
  // Handle --all-builds command
88
94
  if (options.allBuilds) {
89
95
  return runAllBuildsCommand(options)
@@ -130,8 +136,9 @@ export async function run(args: string[]): Promise<number> {
130
136
  }
131
137
 
132
138
  return 0
133
- } catch (error: any) {
134
- console.error(`[Config Exporter] Error: ${error.message}`)
139
+ } catch (error: unknown) {
140
+ const errorMessage = error instanceof Error ? error.message : String(error)
141
+ console.error(`[Config Exporter] Error: ${errorMessage}`)
135
142
  return 1
136
143
  }
137
144
  }
@@ -240,6 +247,16 @@ QUICK START (for troubleshooting):
240
247
  default: false,
241
248
  description: "Export all builds from config file"
242
249
  })
250
+ .option("validate", {
251
+ type: "boolean",
252
+ default: false,
253
+ description:
254
+ "Validate all builds by running webpack/rspack (requires config file)"
255
+ })
256
+ .option("validate-build", {
257
+ type: "string",
258
+ description: "Validate specific build from config file"
259
+ })
243
260
  .option("webpack", {
244
261
  type: "boolean",
245
262
  default: false,
@@ -276,6 +293,16 @@ QUICK START (for troubleshooting):
276
293
  "--build and --all-builds are mutually exclusive. Use one or the other."
277
294
  )
278
295
  }
296
+ if (argv.validate && argv["validate-build"]) {
297
+ throw new Error(
298
+ "--validate and --validate-build are mutually exclusive. Use one or the other."
299
+ )
300
+ }
301
+ if (argv.validate && (argv.build || argv["all-builds"])) {
302
+ throw new Error(
303
+ "--validate cannot be used with --build or --all-builds."
304
+ )
305
+ }
279
306
  return true
280
307
  })
281
308
  .help("help")
@@ -300,6 +327,11 @@ QUICK START (for troubleshooting):
300
327
  bin/export-bundler-config --save-dir=./debug
301
328
  bin/export-bundler-config # Saves to shakapacker-config-exports/
302
329
 
330
+ # Validate builds
331
+ bin/export-bundler-config --validate # Validate all builds
332
+ bin/export-bundler-config --validate-build=dev # Validate specific build
333
+ bin/export-bundler-config --validate --verbose # Validate with full logs
334
+
303
335
  # View config in terminal (stdout)
304
336
  bin/export-bundler-config --stdout
305
337
  bin/export-bundler-config --output=config.yaml # Save to specific file`
@@ -334,7 +366,9 @@ QUICK START (for troubleshooting):
334
366
  configFile: argv["config-file"],
335
367
  build: argv.build,
336
368
  listBuilds: argv["list-builds"],
337
- allBuilds: argv["all-builds"]
369
+ allBuilds: argv["all-builds"],
370
+ validate: argv.validate,
371
+ validateBuild: argv["validate-build"]
338
372
  }
339
373
  }
340
374
 
@@ -392,9 +426,141 @@ function runListBuildsCommand(options: ExportOptions): number {
392
426
  const loader = new ConfigFileLoader(options.configFile)
393
427
  loader.listBuilds()
394
428
  return 0
395
- } catch (error: any) {
396
- console.error(`[Config Exporter] Error: ${error.message}`)
429
+ } catch (error: unknown) {
430
+ const errorMessage = error instanceof Error ? error.message : String(error)
431
+ console.error(`[Config Exporter] Error: ${errorMessage}`)
432
+ return 1
433
+ }
434
+ }
435
+
436
+ async function runValidateCommand(options: ExportOptions): Promise<number> {
437
+ const savedEnv = saveBuildEnvironmentVariables()
438
+
439
+ try {
440
+ // Validate that config file exists
441
+ const loader = new ConfigFileLoader(options.configFile)
442
+ if (!loader.exists()) {
443
+ const configPath = options.configFile || ".bundler-config.yml"
444
+ throw new Error(
445
+ `Config file ${configPath} not found. Run --init to create it.`
446
+ )
447
+ }
448
+
449
+ // Set up environment
450
+ const appRoot = findAppRoot()
451
+ process.chdir(appRoot)
452
+ setupNodePath(appRoot)
453
+
454
+ const config = loader.load()
455
+ const validator = new BuildValidator({ verbose: options.verbose || false })
456
+
457
+ // Determine which builds to validate
458
+ let buildsToValidate: string[]
459
+ if (options.validateBuild) {
460
+ // Validate specific build
461
+ if (!config.builds[options.validateBuild]) {
462
+ const available = Object.keys(config.builds).join(", ")
463
+ throw new Error(
464
+ `Build '${options.validateBuild}' not found in config file.\n` +
465
+ `Available builds: ${available}`
466
+ )
467
+ }
468
+ buildsToValidate = [options.validateBuild]
469
+ } else {
470
+ // Validate all builds
471
+ buildsToValidate = Object.keys(config.builds)
472
+
473
+ // Handle empty builds edge case
474
+ if (buildsToValidate.length === 0) {
475
+ throw new Error(
476
+ `No builds found in config file. Add at least one build to .bundler-config.yml or run --init to see examples.`
477
+ )
478
+ }
479
+ }
480
+
481
+ console.log("\n" + "=".repeat(80))
482
+ console.log("🔍 Validating Builds")
483
+ console.log("=".repeat(80))
484
+ console.log(`\nValidating ${buildsToValidate.length} build(s)...\n`)
485
+
486
+ if (options.verbose) {
487
+ console.log("⚡ VERBOSE MODE ENABLED - Full build output will be shown")
488
+ console.log(
489
+ " This includes all webpack/rspack compilation logs, warnings, and progress messages"
490
+ )
491
+ console.log(" Use without --verbose to see only errors and summaries\n")
492
+ console.log("=".repeat(80) + "\n")
493
+ }
494
+
495
+ const results = []
496
+
497
+ // Validate each build
498
+ for (const buildName of buildsToValidate) {
499
+ if (options.verbose) {
500
+ console.log("\n" + "=".repeat(80))
501
+ console.log(`📦 VALIDATING BUILD: ${buildName}`)
502
+ console.log("=".repeat(80))
503
+ } else {
504
+ console.log(`\n📦 Validating build: ${buildName}`)
505
+ }
506
+
507
+ // Clear and restore environment to prevent leakage between builds
508
+ clearBuildEnvironmentVariables()
509
+ restoreBuildEnvironmentVariables(savedEnv)
510
+
511
+ // Get the build's environment to use for auto-detection
512
+ const buildConfig = config.builds[buildName]
513
+ const buildEnv =
514
+ buildConfig.environment?.NODE_ENV ||
515
+ (buildConfig.environment?.RAILS_ENV as
516
+ | "development"
517
+ | "production"
518
+ | "test"
519
+ | undefined) ||
520
+ "development"
521
+
522
+ // Auto-detect bundler using the build's environment
523
+ const defaultBundler = await autoDetectBundler(buildEnv, appRoot)
524
+
525
+ // Resolve build config with the correct default bundler
526
+ const resolvedBuild = loader.resolveBuild(
527
+ buildName,
528
+ options,
529
+ defaultBundler
530
+ )
531
+
532
+ // Validate the build
533
+ const result = await validator.validateBuild(resolvedBuild, appRoot)
534
+ results.push(result)
535
+
536
+ // Show immediate feedback
537
+ if (options.verbose) {
538
+ console.log("=".repeat(80))
539
+ }
540
+ if (result.success) {
541
+ console.log(` ✅ Build passed`)
542
+ } else {
543
+ console.log(` ❌ Build failed with ${result.errors.length} error(s)`)
544
+ }
545
+ if (options.verbose) {
546
+ console.log("")
547
+ }
548
+ }
549
+
550
+ // Print formatted results
551
+ const formattedResults = validator.formatResults(results)
552
+ console.log(formattedResults)
553
+
554
+ // Return exit code based on results
555
+ const hasFailures = results.some((r) => !r.success)
556
+ return hasFailures ? 1 : 0
557
+ } catch (error: unknown) {
558
+ const errorMessage = error instanceof Error ? error.message : String(error)
559
+ console.error(`[Config Exporter] Error: ${errorMessage}`)
397
560
  return 1
561
+ } finally {
562
+ // Restore original environment
563
+ restoreBuildEnvironmentVariables(savedEnv)
398
564
  }
399
565
  }
400
566
 
@@ -426,7 +592,6 @@ async function runAllBuildsCommand(options: ExportOptions): Promise<number> {
426
592
  `\n📦 Exporting ${buildNames.length} builds from config file...\n`
427
593
  )
428
594
 
429
- const fileWriter = new FileWriter()
430
595
  const targetDir = options.saveDir! // Set by applyDefaults
431
596
  const createdFiles: string[] = []
432
597
 
@@ -444,7 +609,7 @@ async function runAllBuildsCommand(options: ExportOptions): Promise<number> {
444
609
 
445
610
  for (const { config: cfg, metadata } of configs) {
446
611
  const output = formatConfig(cfg, metadata, options, appRoot)
447
- const filename = fileWriter.generateFilename(
612
+ const filename = FileWriter.generateFilename(
448
613
  metadata.bundler,
449
614
  metadata.environment,
450
615
  metadata.configType,
@@ -453,7 +618,7 @@ async function runAllBuildsCommand(options: ExportOptions): Promise<number> {
453
618
  )
454
619
 
455
620
  const fullPath = resolve(targetDir, filename)
456
- fileWriter.writeSingleFile(fullPath, output)
621
+ FileWriter.writeSingleFile(fullPath, output)
457
622
  createdFiles.push(fullPath)
458
623
  }
459
624
  }
@@ -471,8 +636,9 @@ async function runAllBuildsCommand(options: ExportOptions): Promise<number> {
471
636
  console.log("\n" + "=".repeat(80) + "\n")
472
637
 
473
638
  return 0
474
- } catch (error: any) {
475
- console.error(`[Config Exporter] Error: ${error.message}`)
639
+ } catch (error: unknown) {
640
+ const errorMessage = error instanceof Error ? error.message : String(error)
641
+ console.error(`[Config Exporter] Error: ${errorMessage}`)
476
642
  return 1
477
643
  } finally {
478
644
  // Restore original environment
@@ -492,7 +658,6 @@ async function runDoctorMode(
492
658
  console.log("🔍 Config Exporter - Doctor Mode")
493
659
  console.log("=".repeat(80))
494
660
 
495
- const fileWriter = new FileWriter()
496
661
  const targetDir = options.saveDir! // Set by applyDefaults
497
662
 
498
663
  const createdFiles: string[] = []
@@ -526,7 +691,7 @@ async function runDoctorMode(
526
691
 
527
692
  for (const { config, metadata } of configs) {
528
693
  const output = formatConfig(config, metadata, options, appRoot)
529
- const filename = fileWriter.generateFilename(
694
+ const filename = FileWriter.generateFilename(
530
695
  metadata.bundler,
531
696
  metadata.environment,
532
697
  metadata.configType,
@@ -534,7 +699,7 @@ async function runDoctorMode(
534
699
  metadata.buildName
535
700
  )
536
701
  const fullPath = resolve(targetDir, filename)
537
- fileWriter.writeSingleFile(fullPath, output)
702
+ FileWriter.writeSingleFile(fullPath, output)
538
703
  createdFiles.push(fullPath)
539
704
  }
540
705
  }
@@ -543,9 +708,11 @@ async function runDoctorMode(
543
708
  printDoctorSummary(createdFiles, targetDir)
544
709
  return
545
710
  }
546
- } catch (error: any) {
711
+ } catch (error: unknown) {
547
712
  // If config file exists but is invalid, warn and fall through to default behavior
548
- console.log(`\n⚠️ Config file found but invalid: ${error.message}`)
713
+ const errorMessage =
714
+ error instanceof Error ? error.message : String(error)
715
+ console.log(`\n⚠️ Config file found but invalid: ${errorMessage}`)
549
716
  console.log("Falling back to default doctor mode...\n")
550
717
  }
551
718
  }
@@ -592,7 +759,7 @@ async function runDoctorMode(
592
759
  * - Filename uses "client" type and "development-hmr" build name to
593
760
  * distinguish it from regular development client bundle
594
761
  */
595
- filename = fileWriter.generateFilename(
762
+ filename = FileWriter.generateFilename(
596
763
  metadata.bundler,
597
764
  metadata.environment,
598
765
  "client",
@@ -600,7 +767,7 @@ async function runDoctorMode(
600
767
  "development-hmr"
601
768
  )
602
769
  } else {
603
- filename = fileWriter.generateFilename(
770
+ filename = FileWriter.generateFilename(
604
771
  metadata.bundler,
605
772
  metadata.environment,
606
773
  metadata.configType,
@@ -611,7 +778,7 @@ async function runDoctorMode(
611
778
 
612
779
  const fullPath = resolve(targetDir, filename)
613
780
  const fileOutput: FileOutput = { filename, content: output, metadata }
614
- fileWriter.writeSingleFile(fullPath, output)
781
+ FileWriter.writeSingleFile(fullPath, output)
615
782
  createdFiles.push(fullPath)
616
783
  }
617
784
  }
@@ -665,7 +832,6 @@ async function runSaveMode(
665
832
  const env = options.env || "development"
666
833
  console.log(`[Config Exporter] Exporting ${env} configs`)
667
834
 
668
- const fileWriter = new FileWriter()
669
835
  const targetDir = options.saveDir! // Set by applyDefaults
670
836
  const configs = await loadConfigsForEnv(options.env, options, appRoot)
671
837
  const createdFiles: string[] = []
@@ -683,13 +849,13 @@ async function runSaveMode(
683
849
  appRoot
684
850
  )
685
851
  const fullPath = resolve(options.output)
686
- fileWriter.writeSingleFile(fullPath, output)
852
+ FileWriter.writeSingleFile(fullPath, output)
687
853
  createdFiles.push(fullPath)
688
854
  } else {
689
855
  // Multi-file output (one per config)
690
856
  for (const { config, metadata } of configs) {
691
857
  const output = formatConfig(config, metadata, options, appRoot)
692
- const filename = fileWriter.generateFilename(
858
+ const filename = FileWriter.generateFilename(
693
859
  metadata.bundler,
694
860
  metadata.environment,
695
861
  metadata.configType,
@@ -697,7 +863,7 @@ async function runSaveMode(
697
863
  metadata.buildName
698
864
  )
699
865
  const fullPath = resolve(targetDir, filename)
700
- fileWriter.writeSingleFile(fullPath, output)
866
+ FileWriter.writeSingleFile(fullPath, output)
701
867
  createdFiles.push(fullPath)
702
868
  }
703
869
  }
@@ -737,9 +903,8 @@ async function runSingleFileMode(
737
903
  const config = combined.length === 1 ? combined[0] : combined
738
904
  const output = formatConfig(config, metadata, options, appRoot)
739
905
 
740
- const fileWriter = new FileWriter()
741
906
  const filePath = resolve(process.cwd(), options.output!)
742
- fileWriter.writeSingleFile(filePath, output)
907
+ FileWriter.writeSingleFile(filePath, output)
743
908
  }
744
909
 
745
910
  async function loadConfigsForEnv(
@@ -939,9 +1104,11 @@ async function loadConfigsForEnv(
939
1104
  const argv = { mode: finalEnv }
940
1105
  try {
941
1106
  loadedConfig = loadedConfig(envObject, argv)
942
- } catch (error: any) {
1107
+ } catch (error: unknown) {
1108
+ const errorMessage =
1109
+ error instanceof Error ? error.message : String(error)
943
1110
  throw new Error(
944
- `Failed to execute config function: ${error.message}\n` +
1111
+ `Failed to execute config function: ${errorMessage}\n` +
945
1112
  `Config file: ${configFile}\n` +
946
1113
  `Environment: ${JSON.stringify(envObject)}`
947
1114
  )
@@ -1175,7 +1342,7 @@ function loadShakapackerConfig(
1175
1342
  )
1176
1343
  return { bundler, configPath }
1177
1344
  }
1178
- } catch (error: any) {
1345
+ } catch (error: unknown) {
1179
1346
  console.warn(
1180
1347
  `[Config Exporter] Error loading shakapacker config, defaulting to webpack`
1181
1348
  )
@@ -11,16 +11,16 @@ export class FileWriter {
11
11
  /**
12
12
  * Write multiple config files (one per config in array)
13
13
  */
14
- writeMultipleFiles(outputs: FileOutput[], targetDir: string): void {
14
+ static writeMultipleFiles(outputs: FileOutput[], targetDir: string): void {
15
15
  // Ensure directory exists
16
- this.ensureDirectory(targetDir)
16
+ FileWriter.ensureDirectory(targetDir)
17
17
 
18
18
  // Write each file
19
19
  outputs.forEach((output) => {
20
20
  const safeName = basename(output.filename)
21
21
  const filePath = resolve(targetDir, safeName)
22
- this.validateOutputPath(filePath)
23
- this.writeFile(filePath, output.content)
22
+ FileWriter.validateOutputPath(filePath)
23
+ FileWriter.writeFile(filePath, output.content)
24
24
  console.log(`[Config Exporter] Created: ${filePath}`)
25
25
  })
26
26
 
@@ -32,13 +32,13 @@ export class FileWriter {
32
32
  /**
33
33
  * Write a single file
34
34
  */
35
- writeSingleFile(filePath: string, content: string): void {
35
+ static writeSingleFile(filePath: string, content: string): void {
36
36
  // Ensure parent directory exists
37
37
  const dir = dirname(filePath)
38
- this.ensureDirectory(dir)
38
+ FileWriter.ensureDirectory(dir)
39
39
 
40
- this.validateOutputPath(filePath)
41
- this.writeFile(filePath, content)
40
+ FileWriter.validateOutputPath(filePath)
41
+ FileWriter.writeFile(filePath, content)
42
42
  console.log(`[Config Exporter] Created: ${filePath}`)
43
43
  }
44
44
 
@@ -54,7 +54,7 @@ export class FileWriter {
54
54
  * webpack-dev-client.yaml (with build name)
55
55
  * rspack-cypress-dev-server.yaml (with build name)
56
56
  */
57
- generateFilename(
57
+ static generateFilename(
58
58
  bundler: string,
59
59
  env: string,
60
60
  configType: "client" | "server" | "all" | "client-hmr",
@@ -66,11 +66,11 @@ export class FileWriter {
66
66
  return `${bundler}-${name}-${configType}.${ext}`
67
67
  }
68
68
 
69
- private writeFile(filePath: string, content: string): void {
69
+ private static writeFile(filePath: string, content: string): void {
70
70
  writeFileSync(filePath, content, "utf8")
71
71
  }
72
72
 
73
- private ensureDirectory(dir: string): void {
73
+ private static ensureDirectory(dir: string): void {
74
74
  if (!existsSync(dir)) {
75
75
  mkdirSync(dir, { recursive: true })
76
76
  }
@@ -79,7 +79,7 @@ export class FileWriter {
79
79
  /**
80
80
  * Validate output path and warn if writing outside cwd
81
81
  */
82
- validateOutputPath(outputPath: string): void {
82
+ private static validateOutputPath(outputPath: string): void {
83
83
  const absPath = resolve(outputPath)
84
84
  const cwd = process.cwd()
85
85
 
@@ -5,9 +5,11 @@ export type {
5
5
  FileOutput,
6
6
  BundlerConfigFile,
7
7
  BuildConfig,
8
- ResolvedBuildConfig
8
+ ResolvedBuildConfig,
9
+ BuildValidationResult
9
10
  } from "./types"
10
11
  export { YamlSerializer } from "./yamlSerializer"
11
12
  export { FileWriter } from "./fileWriter"
12
13
  export { getDocForKey } from "./configDocs"
13
14
  export { ConfigFileLoader, generateSampleConfigFile } from "./configFile"
15
+ export { BuildValidator } from "./buildValidator"
@@ -18,6 +18,9 @@ export interface ExportOptions {
18
18
  build?: string
19
19
  listBuilds?: boolean
20
20
  allBuilds?: boolean
21
+ // Validation options
22
+ validate?: boolean
23
+ validateBuild?: string
21
24
  }
22
25
 
23
26
  export interface ConfigMetadata {
@@ -34,6 +37,7 @@ export interface ConfigMetadata {
34
37
  CLIENT_BUNDLE_ONLY?: string
35
38
  SERVER_BUNDLE_ONLY?: string
36
39
  WEBPACK_SERVE?: string
40
+ HMR?: string
37
41
  }
38
42
  }
39
43
 
@@ -68,3 +72,17 @@ export interface ResolvedBuildConfig {
68
72
  outputs: string[]
69
73
  configFile?: string
70
74
  }
75
+
76
+ export interface BuildValidationResult {
77
+ buildName: string
78
+ success: boolean
79
+ errors: string[]
80
+ warnings: string[]
81
+ output: string[]
82
+ outputs?: string[] // Build outputs (e.g., ["client", "server"])
83
+ configFile?: string // Config file path if specified
84
+ outputPath?: string // Output directory where files are written
85
+ startTime?: number // Unix timestamp in milliseconds
86
+ endTime?: number // Unix timestamp in milliseconds
87
+ duration?: number // Duration in milliseconds
88
+ }
data/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "shakapacker",
3
- "version": "9.3.0-beta.0",
3
+ "version": "9.3.0-beta.2",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "shakapacker",
9
- "version": "9.3.0-beta.0",
9
+ "version": "9.3.0-beta.2",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "js-yaml": "^4.1.0",
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shakapacker",
3
- "version": "9.3.0-beta.0",
3
+ "version": "9.3.0-beta.2",
4
4
  "description": "Use webpack to manage app-like JavaScript modules in Rails",
5
5
  "homepage": "https://github.com/shakacode/shakapacker",
6
6
  "bugs": {
@@ -49,23 +49,11 @@
49
49
  "yargs": "^17.7.2"
50
50
  },
51
51
  "devDependencies": {
52
+ "@eslint/eslintrc": "^3.2.0",
53
+ "@eslint/js": "^9.37.0",
52
54
  "@rspack/cli": "^1.5.8",
53
55
  "@rspack/core": "^1.5.8",
54
56
  "@swc/core": "^1.3.0",
55
- "babel-loader": "^8.2.4",
56
- "compression-webpack-plugin": "^9.0.0",
57
- "css-loader": "^7.1.2",
58
- "esbuild-loader": "^2.18.0",
59
- "mini-css-extract-plugin": "^2.9.4",
60
- "rspack-manifest-plugin": "^5.0.3",
61
- "sass-loader": "^16.0.5",
62
- "swc-loader": "^0.1.15",
63
- "webpack": "5.93.0",
64
- "webpack-assets-manifest": "^5.0.6",
65
- "webpack-cli": "^6.0.0",
66
- "webpack-subresource-integrity": "^5.1.0",
67
- "@eslint/eslintrc": "^3.2.0",
68
- "@eslint/js": "^9.37.0",
69
57
  "@types/babel__core": "^7.20.5",
70
58
  "@types/js-yaml": "^4.0.9",
71
59
  "@types/node": "^24.5.2",
@@ -76,6 +64,10 @@
76
64
  "@types/yargs": "^17.0.33",
77
65
  "@typescript-eslint/eslint-plugin": "^8.46.0",
78
66
  "@typescript-eslint/parser": "^8.46.0",
67
+ "babel-loader": "^8.2.4",
68
+ "compression-webpack-plugin": "^9.0.0",
69
+ "css-loader": "^7.1.2",
70
+ "esbuild-loader": "^2.18.0",
79
71
  "eslint": "^9.37.0",
80
72
  "eslint-config-airbnb": "^19.0.4",
81
73
  "eslint-config-prettier": "^10.1.8",
@@ -90,9 +82,18 @@
90
82
  "knip": "^5.64.2",
91
83
  "lint-staged": "^15.2.10",
92
84
  "memory-fs": "^0.5.0",
85
+ "mini-css-extract-plugin": "^2.9.4",
93
86
  "prettier": "^3.2.5",
87
+ "rspack-manifest-plugin": "^5.0.3",
88
+ "sass-loader": "^16.0.5",
89
+ "swc-loader": "^0.1.15",
94
90
  "thenify": "^3.3.1",
95
- "typescript": "^5.9.2"
91
+ "ts-jest": "^29.4.5",
92
+ "typescript": "^5.9.2",
93
+ "webpack": "5.93.0",
94
+ "webpack-assets-manifest": "^5.0.6",
95
+ "webpack-cli": "^6.0.0",
96
+ "webpack-subresource-integrity": "^5.1.0"
96
97
  },
97
98
  "peerDependencies": {
98
99
  "@babel/core": "^7.17.9",