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.
- checksums.yaml +4 -4
- data/.eslintrc.fast.js +40 -0
- data/.eslintrc.js +48 -0
- data/.github/workflows/generator.yml +6 -0
- data/.gitignore +1 -4
- data/.npmignore +56 -0
- data/CHANGELOG.md +64 -1
- data/CONTRIBUTING.md +75 -21
- data/Gemfile.lock +1 -1
- data/README.md +4 -0
- data/TODO.md +15 -16
- data/docs/transpiler-migration.md +191 -0
- data/docs/typescript-migration.md +378 -0
- data/lib/install/template.rb +54 -7
- data/lib/shakapacker/version.rb +1 -1
- data/package/.npmignore +4 -0
- data/package/babel/preset.ts +56 -0
- data/package/config.ts +23 -10
- data/package/env.ts +15 -2
- data/package/environments/{development.js → development.ts} +30 -8
- data/package/environments/{production.js → production.ts} +18 -4
- data/package/environments/test.ts +53 -0
- data/package/environments/types.ts +90 -0
- data/package/esbuild/index.ts +42 -0
- data/package/optimization/rspack.ts +36 -0
- data/package/optimization/{webpack.js → webpack.ts} +12 -4
- data/package/plugins/{rspack.js → rspack.ts} +20 -5
- data/package/plugins/{webpack.js → webpack.ts} +2 -2
- data/package/rspack/{index.js → index.ts} +17 -10
- data/package/rules/{babel.js → babel.ts} +1 -1
- data/package/rules/{coffee.js → coffee.ts} +1 -1
- data/package/rules/{css.js → css.ts} +1 -1
- data/package/rules/{erb.js → erb.ts} +1 -1
- data/package/rules/{esbuild.js → esbuild.ts} +2 -2
- data/package/rules/{file.js → file.ts} +11 -6
- data/package/rules/{jscommon.js → jscommon.ts} +4 -4
- data/package/rules/{less.js → less.ts} +3 -3
- data/package/rules/raw.ts +25 -0
- data/package/rules/{rspack.js → rspack.ts} +21 -11
- data/package/rules/{sass.js → sass.ts} +1 -1
- data/package/rules/{stylus.js → stylus.ts} +3 -7
- data/package/rules/{swc.js → swc.ts} +2 -2
- data/package/rules/{webpack.js → webpack.ts} +1 -1
- data/package/swc/index.ts +54 -0
- data/package/types/README.md +87 -0
- data/package/types/index.ts +60 -0
- data/package/utils/errorCodes.ts +219 -0
- data/package/utils/errorHelpers.ts +68 -2
- data/package/utils/pathValidation.ts +139 -0
- data/package/utils/typeGuards.ts +161 -47
- data/package.json +26 -4
- data/scripts/remove-use-strict.js +45 -0
- data/scripts/type-check-no-emit.js +27 -0
- data/test/package/rules/raw.test.js +40 -7
- data/test/package/rules/webpack.test.js +21 -2
- data/test/package/transpiler-defaults.test.js +127 -0
- data/test/scripts/remove-use-strict.test.js +125 -0
- data/test/typescript/build.test.js +3 -2
- data/test/typescript/environments.test.js +107 -0
- data/test/typescript/pathValidation.test.js +142 -0
- data/test/typescript/securityValidation.test.js +182 -0
- data/tsconfig.eslint.json +16 -0
- data/tsconfig.json +9 -10
- data/yarn.lock +415 -6
- metadata +50 -28
- data/package/babel/preset.js +0 -48
- data/package/environments/base.js +0 -103
- data/package/environments/test.js +0 -19
- data/package/esbuild/index.js +0 -40
- data/package/optimization/rspack.js +0 -29
- data/package/rules/raw.js +0 -15
- 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
|
-
"
|
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":
|
30
|
+
"alwaysStrict": true,
|
26
31
|
"allowSyntheticDefaultImports": true,
|
27
32
|
"preserveConstEnums": true,
|
28
33
|
"isolatedModules": true,
|
29
34
|
"removeComments": false
|
30
35
|
},
|
31
|
-
"include": [
|
32
|
-
|
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
|
}
|