shakapacker 9.0.0.beta.6 → 9.0.0.beta.8

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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc.fast.js +40 -0
  3. data/.eslintrc.js +48 -0
  4. data/.github/workflows/generator.yml +6 -0
  5. data/.gitignore +1 -4
  6. data/.npmignore +56 -0
  7. data/CHANGELOG.md +64 -1
  8. data/CONTRIBUTING.md +75 -21
  9. data/Gemfile.lock +1 -1
  10. data/README.md +4 -0
  11. data/TODO.md +15 -16
  12. data/docs/transpiler-migration.md +191 -0
  13. data/docs/typescript-migration.md +378 -0
  14. data/lib/install/template.rb +54 -7
  15. data/lib/shakapacker/version.rb +1 -1
  16. data/package/.npmignore +4 -0
  17. data/package/babel/preset.ts +56 -0
  18. data/package/config.ts +23 -10
  19. data/package/env.ts +15 -2
  20. data/package/environments/{development.js → development.ts} +30 -8
  21. data/package/environments/{production.js → production.ts} +18 -4
  22. data/package/environments/test.ts +53 -0
  23. data/package/environments/types.ts +90 -0
  24. data/package/esbuild/index.ts +42 -0
  25. data/package/optimization/rspack.ts +36 -0
  26. data/package/optimization/{webpack.js → webpack.ts} +12 -4
  27. data/package/plugins/{rspack.js → rspack.ts} +20 -5
  28. data/package/plugins/{webpack.js → webpack.ts} +2 -2
  29. data/package/rspack/{index.js → index.ts} +17 -10
  30. data/package/rules/{babel.js → babel.ts} +1 -1
  31. data/package/rules/{coffee.js → coffee.ts} +1 -1
  32. data/package/rules/{css.js → css.ts} +1 -1
  33. data/package/rules/{erb.js → erb.ts} +1 -1
  34. data/package/rules/{esbuild.js → esbuild.ts} +2 -2
  35. data/package/rules/{file.js → file.ts} +11 -6
  36. data/package/rules/{jscommon.js → jscommon.ts} +4 -4
  37. data/package/rules/{less.js → less.ts} +3 -3
  38. data/package/rules/raw.ts +25 -0
  39. data/package/rules/{rspack.js → rspack.ts} +21 -11
  40. data/package/rules/{sass.js → sass.ts} +1 -1
  41. data/package/rules/{stylus.js → stylus.ts} +3 -7
  42. data/package/rules/{swc.js → swc.ts} +2 -2
  43. data/package/rules/{webpack.js → webpack.ts} +1 -1
  44. data/package/swc/index.ts +54 -0
  45. data/package/types/README.md +87 -0
  46. data/package/types/index.ts +60 -0
  47. data/package/utils/errorCodes.ts +219 -0
  48. data/package/utils/errorHelpers.ts +68 -2
  49. data/package/utils/pathValidation.ts +139 -0
  50. data/package/utils/typeGuards.ts +161 -47
  51. data/package.json +26 -4
  52. data/scripts/remove-use-strict.js +45 -0
  53. data/scripts/type-check-no-emit.js +27 -0
  54. data/test/package/rules/raw.test.js +40 -7
  55. data/test/package/rules/webpack.test.js +21 -2
  56. data/test/package/transpiler-defaults.test.js +127 -0
  57. data/test/scripts/remove-use-strict.test.js +125 -0
  58. data/test/typescript/build.test.js +3 -2
  59. data/test/typescript/environments.test.js +107 -0
  60. data/test/typescript/pathValidation.test.js +142 -0
  61. data/test/typescript/securityValidation.test.js +182 -0
  62. data/tsconfig.eslint.json +16 -0
  63. data/tsconfig.json +9 -10
  64. data/yarn.lock +415 -6
  65. metadata +50 -28
  66. data/package/babel/preset.js +0 -48
  67. data/package/environments/base.js +0 -103
  68. data/package/environments/test.js +0 -19
  69. data/package/esbuild/index.js +0 -40
  70. data/package/optimization/rspack.js +0 -29
  71. data/package/rules/raw.js +0 -15
  72. data/package/swc/index.js +0 -50
@@ -0,0 +1,182 @@
1
+ const {
2
+ isValidConfig,
3
+ clearValidationCache
4
+ } = require("../../package/utils/typeGuards")
5
+
6
+ describe("security validation", () => {
7
+ const originalNodeEnv = process.env.NODE_ENV
8
+ const originalStrictValidation = process.env.SHAKAPACKER_STRICT_VALIDATION
9
+
10
+ afterEach(() => {
11
+ process.env.NODE_ENV = originalNodeEnv
12
+ process.env.SHAKAPACKER_STRICT_VALIDATION = originalStrictValidation
13
+ clearValidationCache()
14
+ })
15
+
16
+ describe("path traversal security checks", () => {
17
+ const baseConfig = {
18
+ source_path: "./app/javascript",
19
+ source_entry_path: "./packs",
20
+ public_root_path: "./public",
21
+ public_output_path: "packs",
22
+ cache_path: "tmp/shakapacker",
23
+ javascript_transpiler: "babel",
24
+ nested_entries: false,
25
+ css_extract_ignore_order_warnings: false,
26
+ webpack_compile_output: true,
27
+ shakapacker_precompile: true,
28
+ cache_manifest: false,
29
+ ensure_consistent_versioning: false,
30
+ useContentHash: true,
31
+ compile: true,
32
+ additional_paths: []
33
+ }
34
+
35
+ it("always validates path traversal in required path fields in production", () => {
36
+ process.env.NODE_ENV = "production"
37
+ delete process.env.SHAKAPACKER_STRICT_VALIDATION
38
+
39
+ const unsafeConfig = {
40
+ ...baseConfig,
41
+ source_path: "../../../etc/passwd"
42
+ }
43
+
44
+ expect(isValidConfig(unsafeConfig)).toBe(false)
45
+ })
46
+
47
+ it("always validates path traversal in required path fields in development", () => {
48
+ process.env.NODE_ENV = "development"
49
+
50
+ const unsafeConfig = {
51
+ ...baseConfig,
52
+ public_output_path: "../../sensitive/data"
53
+ }
54
+
55
+ expect(isValidConfig(unsafeConfig)).toBe(false)
56
+ })
57
+
58
+ it("always validates path traversal in additional_paths in production", () => {
59
+ process.env.NODE_ENV = "production"
60
+ delete process.env.SHAKAPACKER_STRICT_VALIDATION
61
+
62
+ const unsafeConfig = {
63
+ ...baseConfig,
64
+ additional_paths: ["./safe/path", "../../../etc/passwd"]
65
+ }
66
+
67
+ expect(isValidConfig(unsafeConfig)).toBe(false)
68
+ })
69
+
70
+ it("always validates path traversal in additional_paths in development", () => {
71
+ process.env.NODE_ENV = "development"
72
+
73
+ const unsafeConfig = {
74
+ ...baseConfig,
75
+ additional_paths: ["./safe/path", "../../../../root/.ssh"]
76
+ }
77
+
78
+ expect(isValidConfig(unsafeConfig)).toBe(false)
79
+ })
80
+
81
+ it("allows safe paths in production", () => {
82
+ process.env.NODE_ENV = "production"
83
+ delete process.env.SHAKAPACKER_STRICT_VALIDATION
84
+
85
+ const safeConfig = {
86
+ ...baseConfig,
87
+ additional_paths: ["./app/assets", "./vendor/assets", "node_modules"]
88
+ }
89
+
90
+ expect(isValidConfig(safeConfig)).toBe(true)
91
+ })
92
+
93
+ it("allows safe paths in development", () => {
94
+ process.env.NODE_ENV = "development"
95
+
96
+ const safeConfig = {
97
+ ...baseConfig,
98
+ additional_paths: ["./app/components", "./lib/assets"]
99
+ }
100
+
101
+ expect(isValidConfig(safeConfig)).toBe(true)
102
+ })
103
+ })
104
+
105
+ describe("optional field validation", () => {
106
+ const validConfig = {
107
+ source_path: "./app/javascript",
108
+ source_entry_path: "./packs",
109
+ public_root_path: "./public",
110
+ public_output_path: "packs",
111
+ cache_path: "tmp/shakapacker",
112
+ javascript_transpiler: "babel",
113
+ nested_entries: false,
114
+ css_extract_ignore_order_warnings: false,
115
+ webpack_compile_output: true,
116
+ shakapacker_precompile: true,
117
+ cache_manifest: false,
118
+ ensure_consistent_versioning: false,
119
+ useContentHash: true,
120
+ compile: true,
121
+ additional_paths: [],
122
+ dev_server: {
123
+ hmr: true,
124
+ port: 3035
125
+ },
126
+ integrity: {
127
+ enabled: true,
128
+ cross_origin: "anonymous"
129
+ }
130
+ }
131
+
132
+ it("skips deep validation of optional fields in production without strict mode", () => {
133
+ process.env.NODE_ENV = "production"
134
+ delete process.env.SHAKAPACKER_STRICT_VALIDATION
135
+
136
+ // Invalid integrity config that would fail deep validation
137
+ const configWithInvalidOptional = {
138
+ ...validConfig,
139
+ integrity: {
140
+ enabled: "not-a-boolean", // Invalid type
141
+ cross_origin: "anonymous"
142
+ }
143
+ }
144
+
145
+ // Should pass because deep validation is skipped in production
146
+ expect(isValidConfig(configWithInvalidOptional)).toBe(true)
147
+ })
148
+
149
+ it("performs deep validation of optional fields in development", () => {
150
+ process.env.NODE_ENV = "development"
151
+
152
+ // Invalid integrity config
153
+ const configWithInvalidOptional = {
154
+ ...validConfig,
155
+ integrity: {
156
+ enabled: "not-a-boolean", // Invalid type
157
+ cross_origin: "anonymous"
158
+ }
159
+ }
160
+
161
+ // Should fail because deep validation runs in development
162
+ expect(isValidConfig(configWithInvalidOptional)).toBe(false)
163
+ })
164
+
165
+ it("performs deep validation in production with strict mode", () => {
166
+ process.env.NODE_ENV = "production"
167
+ process.env.SHAKAPACKER_STRICT_VALIDATION = "true"
168
+
169
+ // Invalid integrity config
170
+ const configWithInvalidOptional = {
171
+ ...validConfig,
172
+ integrity: {
173
+ enabled: "not-a-boolean", // Invalid type
174
+ cross_origin: "anonymous"
175
+ }
176
+ }
177
+
178
+ // Should fail because strict validation is enabled
179
+ expect(isValidConfig(configWithInvalidOptional)).toBe(false)
180
+ })
181
+ })
182
+ })
@@ -0,0 +1,16 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "noEmit": true,
5
+ "rootDir": "."
6
+ },
7
+ "include": [
8
+ "package/**/*.ts",
9
+ "package/**/*.tsx",
10
+ "package/**/*.test.ts",
11
+ "package/**/*.spec.ts",
12
+ "test/**/*.ts",
13
+ "test/**/*.tsx"
14
+ ],
15
+ "exclude": ["node_modules"]
16
+ }
data/tsconfig.json CHANGED
@@ -3,7 +3,12 @@
3
3
  "target": "ES2020",
4
4
  "module": "commonjs",
5
5
  "lib": ["ES2020"],
6
- "typeRoots": ["./node_modules/@types", "node_modules/@types", "../node_modules/@types"],
6
+ "importHelpers": false,
7
+ "typeRoots": [
8
+ "./node_modules/@types",
9
+ "node_modules/@types",
10
+ "../node_modules/@types"
11
+ ],
7
12
  "declaration": true,
8
13
  "declarationMap": true,
9
14
  "outDir": "./package",
@@ -22,18 +27,12 @@
22
27
  "strictBindCallApply": true,
23
28
  "strictPropertyInitialization": false,
24
29
  "noImplicitThis": true,
25
- "alwaysStrict": false,
30
+ "alwaysStrict": true,
26
31
  "allowSyntheticDefaultImports": true,
27
32
  "preserveConstEnums": true,
28
33
  "isolatedModules": true,
29
34
  "removeComments": false
30
35
  },
31
- "include": [
32
- "package/**/*.ts"
33
- ],
34
- "exclude": [
35
- "node_modules",
36
- "package/**/*.test.ts",
37
- "package/**/*.spec.ts"
38
- ]
36
+ "include": ["package/**/*.ts"],
37
+ "exclude": ["node_modules", "package/**/*.test.ts", "package/**/*.spec.ts"]
39
38
  }