shakapacker 9.0.0.beta.3 → 9.0.0.beta.5

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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/dummy.yml +4 -0
  3. data/.github/workflows/generator.yml +7 -0
  4. data/.github/workflows/node.yml +22 -0
  5. data/.github/workflows/ruby.yml +11 -0
  6. data/.github/workflows/test-bundlers.yml +18 -0
  7. data/.gitignore +20 -0
  8. data/.yalcignore +26 -0
  9. data/CHANGELOG.md +58 -19
  10. data/Gemfile.lock +1 -1
  11. data/README.md +3 -1
  12. data/docs/peer-dependencies.md +23 -3
  13. data/docs/transpiler-performance.md +179 -0
  14. data/docs/typescript.md +99 -0
  15. data/docs/v9_upgrade.md +58 -2
  16. data/lib/install/config/shakapacker.yml +4 -2
  17. data/lib/install/package.json +8 -0
  18. data/lib/install/template.rb +128 -51
  19. data/lib/shakapacker/configuration.rb +58 -1
  20. data/lib/shakapacker/doctor.rb +752 -0
  21. data/lib/shakapacker/swc_migrator.rb +292 -0
  22. data/lib/shakapacker/version.rb +1 -1
  23. data/lib/shakapacker.rb +1 -0
  24. data/lib/tasks/shakapacker/doctor.rake +8 -0
  25. data/lib/tasks/shakapacker/migrate_to_swc.rake +13 -0
  26. data/lib/tasks/shakapacker.rake +1 -0
  27. data/package/config.ts +162 -0
  28. data/package/{dev_server.js → dev_server.ts} +8 -5
  29. data/package/env.ts +67 -0
  30. data/package/environments/base.js +21 -31
  31. data/package/environments/base.ts +137 -0
  32. data/package/index.d.ts +3 -150
  33. data/package/{index.js → index.ts} +17 -8
  34. data/package/loaders.d.ts +27 -0
  35. data/package/types.ts +108 -0
  36. data/package/utils/configPath.ts +6 -0
  37. data/package/utils/{debug.js → debug.ts} +7 -7
  38. data/package/utils/defaultConfigPath.ts +4 -0
  39. data/package/utils/errorHelpers.ts +77 -0
  40. data/package/utils/{getStyleRule.js → getStyleRule.ts} +17 -20
  41. data/package/utils/helpers.ts +85 -0
  42. data/package/utils/{inliningCss.js → inliningCss.ts} +3 -3
  43. data/package/utils/{requireOrError.js → requireOrError.ts} +2 -2
  44. data/package/utils/snakeToCamelCase.ts +5 -0
  45. data/package/utils/typeGuards.ts +228 -0
  46. data/package/utils/{validateDependencies.js → validateDependencies.ts} +4 -4
  47. data/package/webpack-types.d.ts +32 -0
  48. data/package/webpackDevServerConfig.ts +117 -0
  49. data/package.json +6 -2
  50. data/test/package/rules/babel.test.js +16 -0
  51. data/test/typescript/build.test.js +117 -0
  52. data/tsconfig.json +39 -0
  53. data/yarn.lock +5 -5
  54. metadata +32 -18
  55. data/package/config.js +0 -80
  56. data/package/env.js +0 -48
  57. data/package/utils/configPath.js +0 -4
  58. data/package/utils/defaultConfigPath.js +0 -2
  59. data/package/utils/helpers.js +0 -62
  60. data/package/utils/snakeToCamelCase.js +0 -5
  61. data/package/utils/validateCssModulesConfig.js +0 -91
  62. data/package/webpackDevServerConfig.js +0 -73
  63. data/package-lock.json +0 -11966
@@ -1,6 +1,5 @@
1
1
  /* eslint global-require: 0 */
2
2
  /* eslint import/no-dynamic-require: 0 */
3
-
4
3
  const { basename, dirname, join, relative, resolve } = require("path")
5
4
  const { existsSync, readdirSync } = require("fs")
6
5
  const extname = require("path-complete-extname")
@@ -25,15 +24,12 @@ const rules = require(rulesPath)
25
24
  // Don't use contentHash except for production for performance
26
25
  // https://webpack.js.org/guides/build-performance/#avoid-production-specific-tooling
27
26
  const hash = isProduction || config.useContentHash ? "-[contenthash]" : ""
28
-
29
27
  const getFilesInDirectory = (dir, includeNested) => {
30
28
  if (!existsSync(dir)) {
31
29
  return []
32
30
  }
33
-
34
31
  return readdirSync(dir, { withFileTypes: true }).flatMap((dirent) => {
35
32
  const filePath = join(dir, dirent.name)
36
-
37
33
  if (dirent.isDirectory() && includeNested) {
38
34
  return getFilesInDirectory(filePath, includeNested)
39
35
  }
@@ -43,84 +39,78 @@ const getFilesInDirectory = (dir, includeNested) => {
43
39
  return []
44
40
  })
45
41
  }
46
-
47
42
  const getEntryObject = () => {
48
43
  const entries = {}
49
44
  const rootPath = join(config.source_path, config.source_entry_path)
50
45
  if (config.source_entry_path === "/" && config.nested_entries) {
51
46
  throw new Error(
52
- "Your shakapacker config specified using a source_entry_path of '/' with 'nested_entries' == " +
53
- "'true'. Doing this would result in packs for every one of your source files"
47
+ `Invalid Shakapacker configuration detected!\n\n` +
48
+ `You have set source_entry_path to '/' with nested_entries enabled.\n` +
49
+ `This would create webpack entry points for EVERY file in your source directory,\n` +
50
+ `which would severely impact build performance.\n\n` +
51
+ `To fix this issue, either:\n` +
52
+ `1. Set 'nested_entries: false' in your shakapacker.yml\n` +
53
+ `2. Change 'source_entry_path' to a specific subdirectory (e.g., 'packs')\n` +
54
+ `3. Or use both options for better organization of your entry points`
54
55
  )
55
56
  }
56
-
57
57
  getFilesInDirectory(rootPath, config.nested_entries).forEach((path) => {
58
58
  const namespace = relative(join(rootPath), dirname(path))
59
59
  const name = join(namespace, basename(path, extname(path)))
60
- let assetPaths = resolve(path)
61
-
60
+ const assetPath = resolve(path)
62
61
  // Allows for multiple filetypes per entry (https://webpack.js.org/guides/entry-advanced/)
63
62
  // Transforms the config object value to an array with all values under the same name
64
- let previousPaths = entries[name]
63
+ const previousPaths = entries[name]
65
64
  if (previousPaths) {
66
- previousPaths = Array.isArray(previousPaths)
65
+ const pathArray = Array.isArray(previousPaths)
67
66
  ? previousPaths
68
67
  : [previousPaths]
69
- previousPaths.push(assetPaths)
70
- assetPaths = previousPaths
68
+ pathArray.push(assetPath)
69
+ entries[name] = pathArray
70
+ } else {
71
+ entries[name] = assetPath
71
72
  }
72
-
73
- entries[name] = assetPaths
74
73
  })
75
-
76
74
  return entries
77
75
  }
78
-
79
76
  const getModulePaths = () => {
80
77
  const result = [resolve(config.source_path)]
81
-
82
78
  if (config.additional_paths) {
83
79
  config.additional_paths.forEach((path) => result.push(resolve(path)))
84
80
  }
85
81
  result.push("node_modules")
86
-
87
82
  return result
88
83
  }
89
-
90
- module.exports = {
84
+ const baseConfig = {
91
85
  mode: "production",
92
86
  output: {
93
87
  filename: `js/[name]${hash}.js`,
94
88
  chunkFilename: `js/[name]${hash}.chunk.js`,
95
-
96
89
  // https://webpack.js.org/configuration/output/#outputhotupdatechunkfilename
97
90
  hotUpdateChunkFilename: "js/[id].[fullhash].hot-update.js",
98
91
  path: config.outputPath,
99
92
  publicPath: config.publicPath,
100
-
101
93
  // This is required for SRI to work.
102
- crossOriginLoading: config.integrity.enabled
103
- ? config.integrity.cross_origin
104
- : false
94
+ crossOriginLoading:
95
+ config.integrity && config.integrity.enabled
96
+ ? config.integrity.cross_origin
97
+ : false
105
98
  },
106
99
  entry: getEntryObject(),
107
100
  resolve: {
108
101
  extensions: [".js", ".jsx", ".mjs", ".ts", ".tsx", ".coffee"],
109
102
  modules: getModulePaths()
110
103
  },
111
-
112
104
  plugins: getPlugins(),
113
-
114
105
  resolveLoader: {
115
106
  modules: ["node_modules"]
116
107
  },
117
-
118
108
  optimization: {
119
109
  splitChunks: { chunks: "all" },
120
110
  runtimeChunk: "single"
121
111
  },
122
-
123
112
  module: {
124
113
  rules
125
114
  }
126
115
  }
116
+ module.exports = baseConfig
@@ -0,0 +1,137 @@
1
+ /* eslint global-require: 0 */
2
+ /* eslint import/no-dynamic-require: 0 */
3
+
4
+ const { basename, dirname, join, relative, resolve } = require("path")
5
+ const { existsSync, readdirSync } = require("fs")
6
+ import { Dirent } from "fs"
7
+ const extname = require("path-complete-extname")
8
+ import { Configuration, Entry } from "webpack"
9
+ const config = require("../config")
10
+ const { isProduction } = require("../env")
11
+
12
+ const pluginsPath = resolve(
13
+ __dirname,
14
+ "..",
15
+ "plugins",
16
+ `${config.assets_bundler}.js`
17
+ )
18
+ const { getPlugins } = require(pluginsPath)
19
+ const rulesPath = resolve(
20
+ __dirname,
21
+ "..",
22
+ "rules",
23
+ `${config.assets_bundler}.js`
24
+ )
25
+ const rules = require(rulesPath)
26
+
27
+ // Don't use contentHash except for production for performance
28
+ // https://webpack.js.org/guides/build-performance/#avoid-production-specific-tooling
29
+ const hash = isProduction || config.useContentHash ? "-[contenthash]" : ""
30
+
31
+ const getFilesInDirectory = (dir: string, includeNested: boolean): string[] => {
32
+ if (!existsSync(dir)) {
33
+ return []
34
+ }
35
+
36
+ return readdirSync(dir, { withFileTypes: true }).flatMap((dirent: Dirent) => {
37
+ const filePath = join(dir, dirent.name)
38
+
39
+ if (dirent.isDirectory() && includeNested) {
40
+ return getFilesInDirectory(filePath, includeNested)
41
+ }
42
+ if (dirent.isFile()) {
43
+ return filePath
44
+ }
45
+ return []
46
+ })
47
+ }
48
+
49
+ const getEntryObject = (): Entry => {
50
+ const entries: Entry = {}
51
+ const rootPath = join(config.source_path, config.source_entry_path)
52
+ if (config.source_entry_path === "/" && config.nested_entries) {
53
+ throw new Error(
54
+ `Invalid Shakapacker configuration detected!\n\n` +
55
+ `You have set source_entry_path to '/' with nested_entries enabled.\n` +
56
+ `This would create webpack entry points for EVERY file in your source directory,\n` +
57
+ `which would severely impact build performance.\n\n` +
58
+ `To fix this issue, either:\n` +
59
+ `1. Set 'nested_entries: false' in your shakapacker.yml\n` +
60
+ `2. Change 'source_entry_path' to a specific subdirectory (e.g., 'packs')\n` +
61
+ `3. Or use both options for better organization of your entry points`
62
+ )
63
+ }
64
+
65
+ getFilesInDirectory(rootPath, config.nested_entries).forEach((path) => {
66
+ const namespace = relative(join(rootPath), dirname(path))
67
+ const name = join(namespace, basename(path, extname(path)))
68
+ const assetPath: string = resolve(path)
69
+
70
+ // Allows for multiple filetypes per entry (https://webpack.js.org/guides/entry-advanced/)
71
+ // Transforms the config object value to an array with all values under the same name
72
+ const previousPaths = entries[name]
73
+ if (previousPaths) {
74
+ const pathArray = Array.isArray(previousPaths)
75
+ ? previousPaths as string[]
76
+ : [previousPaths as string]
77
+ pathArray.push(assetPath)
78
+ entries[name] = pathArray
79
+ } else {
80
+ entries[name] = assetPath
81
+ }
82
+ })
83
+
84
+ return entries
85
+ }
86
+
87
+ const getModulePaths = (): string[] => {
88
+ const result = [resolve(config.source_path)]
89
+
90
+ if (config.additional_paths) {
91
+ config.additional_paths.forEach((path: string) => result.push(resolve(path)))
92
+ }
93
+ result.push("node_modules")
94
+
95
+ return result
96
+ }
97
+
98
+ const baseConfig: Configuration = {
99
+ mode: "production",
100
+ output: {
101
+ filename: `js/[name]${hash}.js`,
102
+ chunkFilename: `js/[name]${hash}.chunk.js`,
103
+
104
+ // https://webpack.js.org/configuration/output/#outputhotupdatechunkfilename
105
+ hotUpdateChunkFilename: "js/[id].[fullhash].hot-update.js",
106
+ path: config.outputPath,
107
+ publicPath: config.publicPath,
108
+
109
+ // This is required for SRI to work.
110
+ crossOriginLoading: config.integrity && config.integrity.enabled
111
+ ? (config.integrity.cross_origin as "anonymous" | "use-credentials" | false)
112
+ : false
113
+ },
114
+ entry: getEntryObject(),
115
+ resolve: {
116
+ extensions: [".js", ".jsx", ".mjs", ".ts", ".tsx", ".coffee"],
117
+ modules: getModulePaths()
118
+ },
119
+
120
+ plugins: getPlugins(),
121
+
122
+ resolveLoader: {
123
+ modules: ["node_modules"]
124
+ },
125
+
126
+ optimization: {
127
+ splitChunks: { chunks: "all" },
128
+ runtimeChunk: "single"
129
+ },
130
+
131
+ module: {
132
+ rules
133
+ }
134
+ }
135
+
136
+ export = baseConfig
137
+
data/package/index.d.ts CHANGED
@@ -1,150 +1,3 @@
1
- declare module "shakapacker" {
2
- import { Configuration, RuleSetRule } from "webpack"
3
- import * as https from "node:https"
4
-
5
- export interface Config {
6
- source_path: string
7
- source_entry_path: string
8
- nested_entries: boolean
9
- css_extract_ignore_order_warnings: boolean
10
- public_root_path: string
11
- public_output_path: string
12
- private_output_path?: string
13
- cache_path: string
14
- webpack_compile_output: boolean
15
- shakapacker_precompile: boolean
16
- additional_paths: string[]
17
- cache_manifest: boolean
18
- javascript_transpiler: string
19
- ensure_consistent_versioning: boolean
20
- compiler_strategy: string
21
- useContentHash: boolean
22
- compile: boolean
23
- outputPath: string
24
- publicPath: string
25
- publicPathWithoutCDN: string
26
- manifestPath: string
27
- manifest_path?: string
28
- assets_bundler?: string
29
- dev_server?: DevServerConfig
30
- integrity?: {
31
- enabled: boolean
32
- cross_origin: string
33
- hash_functions?: string[]
34
- }
35
- }
36
-
37
- export interface Env {
38
- railsEnv: string
39
- nodeEnv: string
40
- isProduction: boolean
41
- isDevelopment: boolean
42
- runningWebpackDevServer: boolean
43
- }
44
-
45
- type Header =
46
- | Array<{ key: string; value: string }>
47
- | Record<string, string | string[]>
48
- type ServerType = "http" | "https" | "spdy"
49
- type WebSocketType = "sockjs" | "ws"
50
-
51
- /**
52
- * This has the same keys and behavior as https://webpack.js.org/configuration/dev-server/ except:
53
- * 1. `hot` is replaced by `hmr`;
54
- * 2. Camel-cased properties are replaced by snake-cased ones.
55
- * @see {import('webpack-dev-server').Configuration}
56
- */
57
- interface DevServerConfig {
58
- allowed_hosts?: "all" | "auto" | string | string[]
59
- bonjour?: boolean | Record<string, unknown> // bonjour.BonjourOptions
60
- client?: Record<string, unknown> // Client
61
- compress?: boolean
62
- dev_middleware?: Record<string, unknown> // webpackDevMiddleware.Options
63
- headers?: Header | (() => Header)
64
- history_api_fallback?: boolean | Record<string, unknown> // HistoryApiFallbackOptions
65
- hmr?: "only" | boolean
66
- host?: "local-ip" | "local-ipv4" | "local-ipv6" | string
67
- http2?: boolean
68
- https?: boolean | https.ServerOptions
69
- ipc?: boolean | string
70
- magic_html?: boolean
71
- live_reload?: boolean
72
- inline_css?: boolean
73
- env_prefix?: string
74
- open?:
75
- | boolean
76
- | string
77
- | string[]
78
- | Record<string, unknown>
79
- | Record<string, unknown>[]
80
- port?: "auto" | string | number
81
- proxy?: unknown // ProxyConfigMap | ProxyConfigArray
82
- setup_exit_signals?: boolean
83
- static?: boolean | string | unknown // Static | Array<string | Static>
84
- watch_files?: string | string[] | unknown // WatchFiles | Array<WatchFiles | string>
85
- web_socket_server?:
86
- | string
87
- | boolean
88
- | WebSocketType
89
- | {
90
- type?: string | boolean | WebSocketType
91
- options?: Record<string, unknown>
92
- }
93
- server?:
94
- | string
95
- | boolean
96
- | ServerType
97
- | { type?: string | boolean | ServerType; options?: https.ServerOptions }
98
- [otherWebpackDevServerConfigKey: string]: unknown
99
- }
100
-
101
- export const config: Config
102
- export const devServer: DevServerConfig
103
- export function generateWebpackConfig(
104
- extraConfig?: Configuration
105
- ): Configuration
106
- export const baseConfig: Configuration
107
- export const env: Env
108
- export const rules: RuleSetRule[]
109
- export function moduleExists(packageName: string): boolean
110
- export function canProcess<T = unknown>(
111
- rule: string,
112
- fn: (modulePath: string) => T
113
- ): T | null
114
- export const inliningCss: boolean
115
- export * from "webpack-merge"
116
- }
117
-
118
- declare module "shakapacker/rspack" {
119
- import type { RspackOptions } from "@rspack/core"
120
-
121
- export const config: import("shakapacker").Config
122
- export function generateRspackConfig(
123
- extraConfig?: RspackOptions
124
- ): RspackOptions
125
- export const baseConfig: RspackOptions
126
- export const env: import("shakapacker").Env
127
- export const rules: NonNullable<RspackOptions["module"]>["rules"]
128
- export function moduleExists(packageName: string): boolean
129
- export function canProcess<T = unknown>(
130
- rule: string,
131
- fn: (modulePath: string) => T
132
- ): T | null
133
- export const inliningCss: boolean
134
- export * from "webpack-merge"
135
- }
136
-
137
- declare module "shakapacker/package/babel/preset.js" {
138
- import { ConfigAPI, PluginItem, TransformOptions } from "@babel/core"
139
-
140
- interface RequiredTransformOptions {
141
- plugins: PluginItem[]
142
- presets: PluginItem[]
143
- }
144
-
145
- const defaultConfigFunc: (
146
- api: ConfigAPI
147
- ) => TransformOptions & RequiredTransformOptions
148
-
149
- export = defaultConfigFunc
150
- }
1
+ declare const _default: any;
2
+ export = _default;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -2,22 +2,31 @@
2
2
  /* eslint import/no-dynamic-require: 0 */
3
3
 
4
4
  const webpackMerge = require("webpack-merge")
5
- const { resolve } = require("path")
6
- const { existsSync } = require("fs")
5
+ import { resolve } from "path"
6
+ import { existsSync } from "fs"
7
+ import { Configuration } from "webpack"
7
8
  const config = require("./config")
8
9
  const baseConfig = require("./environments/base")
9
-
10
- const rulesPath = resolve(__dirname, "rules", `${config.assets_bundler}.js`)
11
- const rules = require(rulesPath)
12
10
  const devServer = require("./dev_server")
13
11
  const env = require("./env")
14
12
  const { moduleExists, canProcess } = require("./utils/helpers")
15
13
  const inliningCss = require("./utils/inliningCss")
16
14
 
17
- const generateWebpackConfig = (extraConfig = {}, ...extraArgs) => {
15
+ const rulesPath = resolve(__dirname, "rules", `${config.assets_bundler}.js`)
16
+ const rules = require(rulesPath)
17
+
18
+ const generateWebpackConfig = (extraConfig: Configuration = {}, ...extraArgs: any[]): Configuration => {
18
19
  if (extraArgs.length > 0) {
19
20
  throw new Error(
20
- "Only one extra config may be passed here - use webpack-merge to merge configs before passing them to Shakapacker"
21
+ `Invalid usage: generateWebpackConfig() accepts only one configuration object.\n\n` +
22
+ `You passed ${extraArgs.length + 1} arguments. Only one extra config may be passed here - use webpack-merge to merge configs before passing them to Shakapacker.\n\n` +
23
+ `Example:\n` +
24
+ ` const { merge } = require('webpack-merge')\n` +
25
+ ` const mergedConfig = merge(config1, config2, config3)\n` +
26
+ ` const finalConfig = generateWebpackConfig(mergedConfig)\n\n` +
27
+ `Or if using ES6:\n` +
28
+ ` import { merge } from 'webpack-merge'\n` +
29
+ ` const finalConfig = generateWebpackConfig(merge(config1, config2))`
21
30
  )
22
31
  }
23
32
 
@@ -28,7 +37,7 @@ const generateWebpackConfig = (extraConfig = {}, ...extraArgs) => {
28
37
  return webpackMerge.merge({}, environmentConfig, extraConfig)
29
38
  }
30
39
 
31
- module.exports = {
40
+ export = {
32
41
  config, // shakapacker.yml
33
42
  devServer,
34
43
  generateWebpackConfig,
@@ -0,0 +1,27 @@
1
+ import type { LoaderDefinitionFunction } from 'webpack'
2
+
3
+ export interface ShakapackerLoaderOptions {
4
+ [key: string]: any
5
+ }
6
+
7
+ export interface ShakapackerLoader {
8
+ loader: string
9
+ options?: ShakapackerLoaderOptions
10
+ }
11
+
12
+ export type LoaderResolver = (name: string) => string
13
+
14
+ export interface LoaderConfig {
15
+ test: RegExp | ((value: string) => boolean)
16
+ use: Array<string | ShakapackerLoader | LoaderDefinitionFunction>
17
+ exclude?: RegExp | string | Array<string>
18
+ include?: RegExp | string | Array<string>
19
+ type?: string
20
+ generator?: {
21
+ filename?: string
22
+ publicPath?: string
23
+ }
24
+ }
25
+
26
+ export function resolveLoader(name: string): string
27
+ export function createLoader(config: LoaderConfig): LoaderConfig
data/package/types.ts ADDED
@@ -0,0 +1,108 @@
1
+ import * as https from "node:https"
2
+
3
+ // Type for the raw YAML config file
4
+ export interface YamlConfig {
5
+ [environment: string]: Partial<Config>
6
+ }
7
+
8
+ // Type for backward compatibility
9
+ export interface LegacyConfig extends Config {
10
+ webpack_loader?: string
11
+ }
12
+
13
+ export interface Config {
14
+ source_path: string
15
+ source_entry_path: string
16
+ nested_entries: boolean
17
+ css_extract_ignore_order_warnings: boolean
18
+ public_root_path: string
19
+ public_output_path: string
20
+ private_output_path?: string
21
+ cache_path: string
22
+ webpack_compile_output: boolean
23
+ shakapacker_precompile: boolean
24
+ additional_paths: string[]
25
+ cache_manifest: boolean
26
+ javascript_transpiler: string
27
+ ensure_consistent_versioning: boolean
28
+ compiler_strategy: string
29
+ useContentHash: boolean
30
+ compile: boolean
31
+ outputPath: string
32
+ publicPath: string
33
+ publicPathWithoutCDN: string
34
+ manifestPath: string
35
+ manifest_path?: string
36
+ assets_bundler?: string
37
+ dev_server?: DevServerConfig
38
+ integrity?: {
39
+ enabled: boolean
40
+ cross_origin: string
41
+ hash_functions?: string[]
42
+ }
43
+ }
44
+
45
+ export interface Env {
46
+ railsEnv: string
47
+ nodeEnv: string
48
+ isProduction: boolean
49
+ isDevelopment: boolean
50
+ runningWebpackDevServer: boolean
51
+ }
52
+
53
+ type Header =
54
+ | Array<{ key: string; value: string }>
55
+ | Record<string, string | string[]>
56
+ type ServerType = "http" | "https" | "spdy"
57
+ type WebSocketType = "sockjs" | "ws"
58
+
59
+ /**
60
+ * This has the same keys and behavior as https://webpack.js.org/configuration/dev-server/ except:
61
+ * 1. `hot` is replaced by `hmr`;
62
+ * 2. Camel-cased properties are replaced by snake-cased ones.
63
+ * @see {import('webpack-dev-server').Configuration}
64
+ */
65
+ export interface DevServerConfig {
66
+ allowed_hosts?: "all" | "auto" | string | string[]
67
+ bonjour?: boolean | Record<string, unknown> // bonjour.BonjourOptions
68
+ client?: Record<string, unknown> // Client
69
+ compress?: boolean
70
+ dev_middleware?: Record<string, unknown> // webpackDevMiddleware.Options
71
+ headers?: Header | (() => Header)
72
+ history_api_fallback?: boolean | Record<string, unknown> // HistoryApiFallbackOptions
73
+ hmr?: "only" | boolean
74
+ host?: "local-ip" | "local-ipv4" | "local-ipv6" | string
75
+ http2?: boolean
76
+ https?: boolean | https.ServerOptions
77
+ ipc?: boolean | string
78
+ magic_html?: boolean
79
+ live_reload?: boolean
80
+ inline_css?: boolean
81
+ env_prefix?: string
82
+ open?:
83
+ | boolean
84
+ | string
85
+ | string[]
86
+ | Record<string, unknown>
87
+ | Record<string, unknown>[]
88
+ port?: "auto" | string | number
89
+ proxy?: unknown // ProxyConfigMap | ProxyConfigArray
90
+ setup_exit_signals?: boolean
91
+ static?: boolean | string | unknown // Static | Array<string | Static>
92
+ watch_files?: string | string[] | unknown // WatchFiles | Array<WatchFiles | string>
93
+ web_socket_server?:
94
+ | string
95
+ | boolean
96
+ | WebSocketType
97
+ | {
98
+ type?: string | boolean | WebSocketType
99
+ options?: Record<string, unknown>
100
+ }
101
+ server?:
102
+ | string
103
+ | boolean
104
+ | ServerType
105
+ | { type?: string | boolean | ServerType; options?: https.ServerOptions }
106
+ [otherWebpackDevServerConfigKey: string]: unknown
107
+ }
108
+
@@ -0,0 +1,6 @@
1
+ import { resolve } from "path"
2
+
3
+ const configPath: string =
4
+ process.env.SHAKAPACKER_CONFIG || resolve("config", "shakapacker.yml")
5
+
6
+ export = configPath
@@ -3,7 +3,7 @@
3
3
  * Provides conditional logging based on environment variables
4
4
  */
5
5
 
6
- const isDebugMode = () => {
6
+ const isDebugMode = (): boolean => {
7
7
  // Explicitly check for debug mode being disabled
8
8
  if (process.env.SHAKAPACKER_DEBUG === "false") {
9
9
  return false
@@ -16,34 +16,34 @@ const isDebugMode = () => {
16
16
  )
17
17
  }
18
18
 
19
- const debug = (message, ...args) => {
19
+ const debug = (message: string, ...args: any[]): void => {
20
20
  if (isDebugMode()) {
21
21
  // eslint-disable-next-line no-console
22
22
  console.log(`[Shakapacker] ${message}`, ...args)
23
23
  }
24
24
  }
25
25
 
26
- const warn = (message, ...args) => {
26
+ const warn = (message: string, ...args: any[]): void => {
27
27
  // eslint-disable-next-line no-console
28
28
  console.warn(`[Shakapacker] WARNING: ${message}`, ...args)
29
29
  }
30
30
 
31
- const error = (message, ...args) => {
31
+ const error = (message: string, ...args: any[]): void => {
32
32
  // eslint-disable-next-line no-console
33
33
  console.error(`[Shakapacker] ERROR: ${message}`, ...args)
34
34
  }
35
35
 
36
- const info = (message, ...args) => {
36
+ const info = (message: string, ...args: any[]): void => {
37
37
  if (isDebugMode()) {
38
38
  // eslint-disable-next-line no-console
39
39
  console.info(`[Shakapacker] INFO: ${message}`, ...args)
40
40
  }
41
41
  }
42
42
 
43
- module.exports = {
43
+ export = {
44
44
  debug,
45
45
  warn,
46
46
  error,
47
47
  info,
48
48
  isDebugMode
49
- }
49
+ }
@@ -0,0 +1,4 @@
1
+ import { resolve } from "path"
2
+
3
+ const path: string = resolve(__dirname, "../../lib/install/config/shakapacker.yml")
4
+ export = path