es-guard 1.7.0 → 1.9.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.
- package/dist/cli.js +17 -7
- package/dist/lib/defaults.js +77 -0
- package/dist/lib/detectTarget.js +15 -78
- package/dist/lib/globalState.js +30 -1
- package/dist/lib/projectType.js +46 -0
- package/dist/lib/utils.js +76 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -5,6 +5,7 @@ import packageJson from "../package.json" with { type: "json" };
|
|
|
5
5
|
import { checkCompatibility, formatViolationMessage } from "./lib/checkCompatiblity.js";
|
|
6
6
|
import { getBrowserTargetsFromString } from "./lib/getBrowserTargets.js";
|
|
7
7
|
import { detectProjectConfig, getConfigFileNames } from "./lib/detectTarget.js";
|
|
8
|
+
import { getCurrentProjectType } from "./lib/projectType.js";
|
|
8
9
|
import { setVerboseMode } from "./lib/globalState.js";
|
|
9
10
|
const version = packageJson.version;
|
|
10
11
|
// Create the main program
|
|
@@ -18,6 +19,7 @@ program
|
|
|
18
19
|
.option("-t, --target <version>", "Target ES version (2015, 2016, 2017, etc. or 6, 7, 8, etc. or 'latest'). If not specified, will auto-detect from project config files.")
|
|
19
20
|
.option("-b, --browsers <targets>", "Browser targets for compatibility checking (optional: auto-determined from target)")
|
|
20
21
|
.option("-v, --verbose", "Enable verbose output showing detailed detection process and configuration information")
|
|
22
|
+
.option("--skip", "Do not exit with error code when compatibility errors are found")
|
|
21
23
|
.addHelpText("after", `
|
|
22
24
|
|
|
23
25
|
Examples:
|
|
@@ -28,6 +30,7 @@ Examples:
|
|
|
28
30
|
es-guard -t latest build # Check 'build' directory with latest ES (auto-determined browsers)
|
|
29
31
|
es-guard --target 2017 --browsers "> 0.5%, last 2 versions" dist
|
|
30
32
|
es-guard --verbose # Auto-detect with detailed detection information
|
|
33
|
+
es-guard --skip # Auto-detect and continue even if compatibility errors are found
|
|
31
34
|
|
|
32
35
|
Auto-detection searches for ES target in:
|
|
33
36
|
- package.json (browserslist field)
|
|
@@ -51,7 +54,7 @@ Browser targets use Browserslist format:
|
|
|
51
54
|
|
|
52
55
|
Exit codes:
|
|
53
56
|
0 - No compatibility issues found
|
|
54
|
-
1 - Compatibility issues found or error occurred
|
|
57
|
+
1 - Compatibility issues found or error occurred (unless --skip is used)
|
|
55
58
|
`);
|
|
56
59
|
// Add validation for the target option
|
|
57
60
|
program.hook("preAction", (thisCommand) => {
|
|
@@ -80,6 +83,9 @@ program.action(async (directory, options) => {
|
|
|
80
83
|
if (options.verbose) {
|
|
81
84
|
console.log("🔍 Auto-detecting project configuration...");
|
|
82
85
|
console.log(`📂 Searching in: ${process.cwd()}`);
|
|
86
|
+
// Detect and log project type
|
|
87
|
+
const projectType = getCurrentProjectType();
|
|
88
|
+
console.log(`🏗️ Project type: ${projectType}`);
|
|
83
89
|
console.log("");
|
|
84
90
|
}
|
|
85
91
|
// Use unified detection to get all configuration at once
|
|
@@ -210,13 +216,17 @@ program.action(async (directory, options) => {
|
|
|
210
216
|
}
|
|
211
217
|
}
|
|
212
218
|
if (errors.length > 0) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
console.log("✅ No compatibility errors found!");
|
|
217
|
-
if (warnings.length > 0) {
|
|
218
|
-
console.log("⚠️ There are compat warnings, but no syntax errors. Please address these warnings and update polyfills in your app and in es-guard config.");
|
|
219
|
+
if (options.skip) {
|
|
220
|
+
console.log("⚠️ Compatibility errors found, but continuing due to --skip option");
|
|
221
|
+
process.exit(0);
|
|
219
222
|
}
|
|
223
|
+
else {
|
|
224
|
+
process.exit(1);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
console.log("✅ No compatibility errors found!");
|
|
228
|
+
if (warnings.length > 0) {
|
|
229
|
+
console.log("⚠️ There are compat warnings, but no syntax errors. Please address these warnings and update polyfills in your app and in es-guard config.");
|
|
220
230
|
}
|
|
221
231
|
}
|
|
222
232
|
catch (error) {
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default configurations for different project types
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Next.js default browserslist configuration
|
|
6
|
+
* Source: https://nextjs.org/docs/basic-features/supported-browsers-features
|
|
7
|
+
*/
|
|
8
|
+
export const NEXTJS_DEFAULT_BROWSERSLIST = ["chrome 64", "edge 79", "firefox 67", "opera 51", "safari 12"];
|
|
9
|
+
/**
|
|
10
|
+
* Default output directories for different project types
|
|
11
|
+
*/
|
|
12
|
+
export const DEFAULT_OUTPUT_DIRS = {
|
|
13
|
+
nextjs: ".next/static",
|
|
14
|
+
vite: "dist",
|
|
15
|
+
webpack: "dist",
|
|
16
|
+
rollup: "dist",
|
|
17
|
+
parcel: "dist",
|
|
18
|
+
generic: "dist",
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Project type detection helpers
|
|
22
|
+
*/
|
|
23
|
+
export const PROJECT_TYPES = {
|
|
24
|
+
nextjs: "nextjs",
|
|
25
|
+
vite: "vite",
|
|
26
|
+
webpack: "webpack",
|
|
27
|
+
rollup: "rollup",
|
|
28
|
+
parcel: "parcel",
|
|
29
|
+
generic: "generic",
|
|
30
|
+
};
|
|
31
|
+
export const ProjectTypeKeys = new Set(Object.keys(PROJECT_TYPES));
|
|
32
|
+
export const isProjectType = (projectType) => {
|
|
33
|
+
return ProjectTypeKeys.has(projectType);
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Get default browserslist for a project type
|
|
37
|
+
*/
|
|
38
|
+
export function getDefaultBrowserslist(projectType) {
|
|
39
|
+
switch (projectType) {
|
|
40
|
+
case PROJECT_TYPES.nextjs:
|
|
41
|
+
return [...NEXTJS_DEFAULT_BROWSERSLIST];
|
|
42
|
+
// Add more project types here as needed
|
|
43
|
+
default:
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get default output directory for a project type
|
|
49
|
+
*/
|
|
50
|
+
export function getDefaultOutputDir(projectType) {
|
|
51
|
+
if (isProjectType(projectType)) {
|
|
52
|
+
return DEFAULT_OUTPUT_DIRS[projectType];
|
|
53
|
+
}
|
|
54
|
+
return DEFAULT_OUTPUT_DIRS.generic;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Detect project type from package.json dependencies
|
|
58
|
+
*/
|
|
59
|
+
export function detectProjectType(dependencies = {}, devDependencies = {}) {
|
|
60
|
+
const allDeps = { ...dependencies, ...devDependencies };
|
|
61
|
+
if (allDeps.next) {
|
|
62
|
+
return PROJECT_TYPES.nextjs;
|
|
63
|
+
}
|
|
64
|
+
if (allDeps.vite) {
|
|
65
|
+
return PROJECT_TYPES.vite;
|
|
66
|
+
}
|
|
67
|
+
if (allDeps.webpack) {
|
|
68
|
+
return PROJECT_TYPES.webpack;
|
|
69
|
+
}
|
|
70
|
+
if (allDeps.rollup) {
|
|
71
|
+
return PROJECT_TYPES.rollup;
|
|
72
|
+
}
|
|
73
|
+
if (allDeps.parcel) {
|
|
74
|
+
return PROJECT_TYPES.parcel;
|
|
75
|
+
}
|
|
76
|
+
return PROJECT_TYPES.generic;
|
|
77
|
+
}
|
package/dist/lib/detectTarget.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import * as fs from "fs";
|
|
2
2
|
import * as path from "path";
|
|
3
3
|
import { verboseMode } from "./globalState.js";
|
|
4
|
+
import { NEXTJS_DEFAULT_BROWSERSLIST } from "./defaults.js";
|
|
5
|
+
import { getCurrentProjectType } from "./projectType.js";
|
|
6
|
+
import { readJsonFile, readTextFile, evaluateJsFile, isPackageJson, isTsConfig, isBabelRc, isViteConfig, isWebpackConfig, isNextConfig, } from "./utils.js";
|
|
4
7
|
// Shared utilities for ES version parsing and conversion
|
|
5
8
|
const CONFIG_FILE_NAMES = [
|
|
6
9
|
"package.json",
|
|
@@ -52,80 +55,6 @@ const TARGET_MAP = {
|
|
|
52
55
|
es6: "2015",
|
|
53
56
|
es5: "2009",
|
|
54
57
|
};
|
|
55
|
-
/**
|
|
56
|
-
* Helper to read and parse JSON file safely
|
|
57
|
-
*/
|
|
58
|
-
const readJsonFile = (filePath) => {
|
|
59
|
-
const content = fs.readFileSync(filePath, "utf-8");
|
|
60
|
-
return JSON.parse(content);
|
|
61
|
-
};
|
|
62
|
-
/**
|
|
63
|
-
* Helper to read text file safely
|
|
64
|
-
*/
|
|
65
|
-
const readTextFile = (filePath) => {
|
|
66
|
-
return fs.readFileSync(filePath, "utf-8");
|
|
67
|
-
};
|
|
68
|
-
/**
|
|
69
|
-
* Helper to safely evaluate JavaScript files (for config files)
|
|
70
|
-
*/
|
|
71
|
-
const evaluateJsFile = (filePath) => {
|
|
72
|
-
const content = readTextFile(filePath);
|
|
73
|
-
// Create a safe evaluation context
|
|
74
|
-
const module = { exports: {} };
|
|
75
|
-
const require = (id) => {
|
|
76
|
-
if (id === "path")
|
|
77
|
-
return path;
|
|
78
|
-
if (id === "fs")
|
|
79
|
-
return fs;
|
|
80
|
-
throw new Error(`Cannot require '${id}' in config evaluation`);
|
|
81
|
-
};
|
|
82
|
-
try {
|
|
83
|
-
// Use Function constructor to create a safe evaluation environment
|
|
84
|
-
const fn = new Function("module", "exports", "require", "path", "fs", "__dirname", content);
|
|
85
|
-
fn(module, module.exports, require, path, fs, path.dirname(filePath));
|
|
86
|
-
return module.exports;
|
|
87
|
-
}
|
|
88
|
-
catch (error) {
|
|
89
|
-
console.warn(`Error evaluating ${filePath}:`, error);
|
|
90
|
-
return null;
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
/**
|
|
94
|
-
* Type guard for package.json structure
|
|
95
|
-
*/
|
|
96
|
-
const isPackageJson = (obj) => {
|
|
97
|
-
return typeof obj === "object" && obj !== null;
|
|
98
|
-
};
|
|
99
|
-
/**
|
|
100
|
-
* Type guard for tsconfig.json structure
|
|
101
|
-
*/
|
|
102
|
-
const isTsConfig = (obj) => {
|
|
103
|
-
return typeof obj === "object" && obj !== null && "compilerOptions" in obj;
|
|
104
|
-
};
|
|
105
|
-
/**
|
|
106
|
-
* Type guard for .babelrc structure
|
|
107
|
-
*/
|
|
108
|
-
const isBabelRc = (obj) => {
|
|
109
|
-
return typeof obj === "object" && obj !== null && "presets" in obj;
|
|
110
|
-
};
|
|
111
|
-
/**
|
|
112
|
-
* Type guard for vite config structure
|
|
113
|
-
*/
|
|
114
|
-
const isViteConfig = (obj) => {
|
|
115
|
-
return typeof obj === "object" && obj !== null;
|
|
116
|
-
};
|
|
117
|
-
/**
|
|
118
|
-
* Type guard for webpack config structure
|
|
119
|
-
*/
|
|
120
|
-
const isWebpackConfig = (obj) => {
|
|
121
|
-
return typeof obj === "object" && obj !== null;
|
|
122
|
-
};
|
|
123
|
-
/**
|
|
124
|
-
* Type guard for next.js config structure
|
|
125
|
-
*/
|
|
126
|
-
const isNextConfig = (obj) => {
|
|
127
|
-
return typeof obj === "object" && obj !== null;
|
|
128
|
-
};
|
|
129
58
|
/**
|
|
130
59
|
* Get parser function for a given config file
|
|
131
60
|
*/
|
|
@@ -212,7 +141,7 @@ export const detectProjectConfig = (cwd = process.cwd()) => {
|
|
|
212
141
|
// Update output directory if found and not already set
|
|
213
142
|
if (detection.outputDir && !result.outputDir) {
|
|
214
143
|
result.outputDir = detection.outputDir;
|
|
215
|
-
result.outputSource = filename;
|
|
144
|
+
result.outputSource = detection.outputSource || filename;
|
|
216
145
|
if (verboseMode) {
|
|
217
146
|
console.log(` 📁 Output directory: ${detection.outputDir}`);
|
|
218
147
|
}
|
|
@@ -226,7 +155,7 @@ export const detectProjectConfig = (cwd = process.cwd()) => {
|
|
|
226
155
|
// Update browserslist if found and not already set
|
|
227
156
|
if (detection.browserslist && !result.browserslist) {
|
|
228
157
|
result.browserslist = detection.browserslist;
|
|
229
|
-
result.browserslistSource = filename;
|
|
158
|
+
result.browserslistSource = detection.browserslistSource || filename;
|
|
230
159
|
if (verboseMode) {
|
|
231
160
|
console.log(` 🌐 Browserslist: ${detection.browserslist.join(", ")} (from ${result.browserslistSource})`);
|
|
232
161
|
}
|
|
@@ -335,6 +264,8 @@ const parsePackageJson = (filePath) => {
|
|
|
335
264
|
// Store the full browserslist for CLI defaults
|
|
336
265
|
result.browserslist = browserslist.filter((browser) => typeof browser === "string");
|
|
337
266
|
}
|
|
267
|
+
// Use global project type detection (lazy initialization)
|
|
268
|
+
const projectType = getCurrentProjectType(path.dirname(filePath));
|
|
338
269
|
// Check for output directory hints
|
|
339
270
|
if (pkg.dist) {
|
|
340
271
|
result.outputDir = pkg.dist;
|
|
@@ -345,9 +276,15 @@ const parsePackageJson = (filePath) => {
|
|
|
345
276
|
else if (pkg.main && pkg.main.startsWith("./dist/")) {
|
|
346
277
|
result.outputDir = "dist";
|
|
347
278
|
}
|
|
348
|
-
else if (
|
|
349
|
-
//
|
|
279
|
+
else if (projectType === "nextjs") {
|
|
280
|
+
// Set default output directory for Next.js projects
|
|
350
281
|
result.outputDir = ".next/static";
|
|
282
|
+
result.outputSource = "package.json (default)";
|
|
283
|
+
}
|
|
284
|
+
// If no browserslist was found, use default for detected project type
|
|
285
|
+
if (!result.browserslist && projectType === "nextjs") {
|
|
286
|
+
result.browserslist = [...NEXTJS_DEFAULT_BROWSERSLIST];
|
|
287
|
+
result.browserslistSource = "Next.js default";
|
|
351
288
|
}
|
|
352
289
|
return result;
|
|
353
290
|
};
|
package/dist/lib/globalState.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
// Global state management for CLI options
|
|
1
|
+
// Global state management for CLI options and project configuration
|
|
2
2
|
// Static global state variables
|
|
3
3
|
export let verboseMode = false;
|
|
4
4
|
export let debugMode = false;
|
|
5
|
+
export let projectType = undefined;
|
|
6
|
+
export let projectTypeDetected = false;
|
|
5
7
|
/**
|
|
6
8
|
* Set the global verbose mode
|
|
7
9
|
*/
|
|
@@ -21,6 +23,8 @@ export const getGlobalState = () => {
|
|
|
21
23
|
return {
|
|
22
24
|
verbose: verboseMode,
|
|
23
25
|
debug: debugMode,
|
|
26
|
+
projectType,
|
|
27
|
+
projectTypeDetected,
|
|
24
28
|
};
|
|
25
29
|
};
|
|
26
30
|
/**
|
|
@@ -31,6 +35,10 @@ export const setGlobalState = (options) => {
|
|
|
31
35
|
verboseMode = options.verbose;
|
|
32
36
|
if (options.debug !== undefined)
|
|
33
37
|
debugMode = options.debug;
|
|
38
|
+
if (options.projectType !== undefined)
|
|
39
|
+
projectType = options.projectType;
|
|
40
|
+
if (options.projectTypeDetected !== undefined)
|
|
41
|
+
projectTypeDetected = options.projectTypeDetected;
|
|
34
42
|
};
|
|
35
43
|
/**
|
|
36
44
|
* Reset global state to defaults
|
|
@@ -38,4 +46,25 @@ export const setGlobalState = (options) => {
|
|
|
38
46
|
export const resetGlobalState = () => {
|
|
39
47
|
verboseMode = false;
|
|
40
48
|
debugMode = false;
|
|
49
|
+
projectType = undefined;
|
|
50
|
+
projectTypeDetected = false;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Set the detected project type globally
|
|
54
|
+
*/
|
|
55
|
+
export const setProjectType = (detectedType) => {
|
|
56
|
+
projectType = detectedType;
|
|
57
|
+
projectTypeDetected = true;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Get the detected project type (lazy detection if not already done)
|
|
61
|
+
*/
|
|
62
|
+
export const getProjectType = () => {
|
|
63
|
+
return projectType;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Check if project type has been detected
|
|
67
|
+
*/
|
|
68
|
+
export const isProjectTypeDetected = () => {
|
|
69
|
+
return projectTypeDetected;
|
|
41
70
|
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import { verboseMode, setProjectType, getProjectType, isProjectTypeDetected } from "./globalState.js";
|
|
4
|
+
import { detectProjectType } from "./defaults.js";
|
|
5
|
+
import { readJsonFile, isPackageJson } from "./utils.js";
|
|
6
|
+
/**
|
|
7
|
+
* Detect and cache project type globally (lazy initialization)
|
|
8
|
+
*/
|
|
9
|
+
export const detectAndCacheProjectType = (cwd = process.cwd()) => {
|
|
10
|
+
// Return cached result if already detected
|
|
11
|
+
if (isProjectTypeDetected()) {
|
|
12
|
+
return getProjectType() || null;
|
|
13
|
+
}
|
|
14
|
+
// Detect project type from package.json
|
|
15
|
+
const packageJsonPath = path.join(cwd, "package.json");
|
|
16
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
17
|
+
try {
|
|
18
|
+
const pkg = readJsonFile(packageJsonPath);
|
|
19
|
+
if (isPackageJson(pkg)) {
|
|
20
|
+
const detectedType = detectProjectType(pkg.dependencies, pkg.devDependencies);
|
|
21
|
+
setProjectType(detectedType);
|
|
22
|
+
if (verboseMode) {
|
|
23
|
+
console.log(`🔍 Project type detected: ${detectedType}`);
|
|
24
|
+
}
|
|
25
|
+
return detectedType;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
// Ignore errors when detecting project type
|
|
30
|
+
if (verboseMode) {
|
|
31
|
+
console.log(` ⚠️ Error detecting project type: ${error instanceof Error ? error.message : String(error)}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// No project type detected
|
|
36
|
+
if (verboseMode) {
|
|
37
|
+
console.log(`🔍 No project type detected`);
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Get the current project type (detects if not already cached)
|
|
43
|
+
*/
|
|
44
|
+
export const getCurrentProjectType = (cwd = process.cwd()) => {
|
|
45
|
+
return detectAndCacheProjectType(cwd) || "generic";
|
|
46
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
/**
|
|
4
|
+
* Helper to read and parse JSON file safely
|
|
5
|
+
*/
|
|
6
|
+
export const readJsonFile = (filePath) => {
|
|
7
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
8
|
+
return JSON.parse(content);
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Helper to read text file safely
|
|
12
|
+
*/
|
|
13
|
+
export const readTextFile = (filePath) => {
|
|
14
|
+
return fs.readFileSync(filePath, "utf-8");
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Helper to safely evaluate JavaScript files (for config files)
|
|
18
|
+
*/
|
|
19
|
+
export const evaluateJsFile = (filePath) => {
|
|
20
|
+
const content = readTextFile(filePath);
|
|
21
|
+
// Create a safe evaluation context
|
|
22
|
+
const module = { exports: {} };
|
|
23
|
+
const require = (id) => {
|
|
24
|
+
if (id === "path")
|
|
25
|
+
return path;
|
|
26
|
+
if (id === "fs")
|
|
27
|
+
return fs;
|
|
28
|
+
throw new Error(`Cannot require '${id}' in config evaluation`);
|
|
29
|
+
};
|
|
30
|
+
try {
|
|
31
|
+
// Use Function constructor to create a safe evaluation environment
|
|
32
|
+
const fn = new Function("module", "exports", "require", "path", "fs", "__dirname", content);
|
|
33
|
+
fn(module, module.exports, require, path, fs, path.dirname(filePath));
|
|
34
|
+
return module.exports;
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
console.warn(`Error evaluating ${filePath}:`, error);
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Type guard for package.json structure
|
|
43
|
+
*/
|
|
44
|
+
export const isPackageJson = (obj) => {
|
|
45
|
+
return typeof obj === "object" && obj !== null;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Type guard for tsconfig.json structure
|
|
49
|
+
*/
|
|
50
|
+
export const isTsConfig = (obj) => {
|
|
51
|
+
return typeof obj === "object" && obj !== null && "compilerOptions" in obj;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Type guard for .babelrc structure
|
|
55
|
+
*/
|
|
56
|
+
export const isBabelRc = (obj) => {
|
|
57
|
+
return typeof obj === "object" && obj !== null && "presets" in obj;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Type guard for vite config structure
|
|
61
|
+
*/
|
|
62
|
+
export const isViteConfig = (obj) => {
|
|
63
|
+
return typeof obj === "object" && obj !== null;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Type guard for webpack config structure
|
|
67
|
+
*/
|
|
68
|
+
export const isWebpackConfig = (obj) => {
|
|
69
|
+
return typeof obj === "object" && obj !== null;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Type guard for next.js config structure
|
|
73
|
+
*/
|
|
74
|
+
export const isNextConfig = (obj) => {
|
|
75
|
+
return typeof obj === "object" && obj !== null;
|
|
76
|
+
};
|