tsfmt 0.0.0 → 0.2.1
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/README.md +1 -1
- package/dist/build-plugins/transformGenericsPlugin.js +86 -0
- package/dist/cli.js +174 -0
- package/dist/core/ast/ASTAnalyzer.js +136 -0
- package/dist/core/ast/ASTTransformer.js +85 -0
- package/dist/core/ast/DependencyResolver.js +144 -0
- package/dist/core/config/ConfigDefaults.js +178 -0
- package/dist/core/config/ConfigLoader.js +251 -0
- package/dist/core/config/ConfigMerger.js +45 -0
- package/dist/core/config/ConfigTypes.js +70 -0
- package/dist/core/config/ConfigValidator.js +74 -0
- package/dist/core/di/Container.js +175 -0
- package/dist/core/di/ServiceRegistration.js +38 -0
- package/dist/core/formatters/BaseFormattingRule.js +37 -0
- package/dist/core/formatters/rules/ast/ClassMemberSortingRule.js +171 -0
- package/dist/core/formatters/rules/ast/FileDeclarationSortingRule.js +162 -0
- package/dist/core/formatters/rules/imports/ImportOrganizationRule.js +196 -0
- package/dist/core/formatters/rules/index-generation/IndexGenerationRule.js +208 -0
- package/dist/core/formatters/rules/spacing/BlankLineBeforeReturnsRule.js +32 -0
- package/dist/core/formatters/rules/spacing/BlankLineBetweenDeclarationsRule.js +93 -0
- package/dist/core/formatters/rules/spacing/BlankLineBetweenStatementTypesRule.js +57 -0
- package/dist/core/formatters/rules/spacing/BlockSpacingRule.js +17 -0
- package/dist/core/formatters/rules/spacing/BracketSpacingRule.js +108 -0
- package/dist/core/formatters/rules/style/DocBlockCommentRule.js +19 -0
- package/dist/core/formatters/rules/style/IndentationRule.js +45 -0
- package/dist/core/formatters/rules/style/QuoteStyleRule.js +63 -0
- package/dist/core/formatters/rules/style/SemicolonRule.js +68 -0
- package/dist/core/formatters/rules/style/StructuralIndentationRule.js +250 -0
- package/dist/core/pipeline/FormatterPipeline.js +252 -0
- package/dist/formatters/package.js +29 -0
- package/dist/index.js +66 -0
- package/dist/shared/types.js +28 -0
- package/dist/sortPackage.js +34 -0
- package/dist/sortTSConfig.js +34 -0
- package/package.json +11 -8
- package/bin/ci_build.sh +0 -50
- package/bin/cli.js +0 -20
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
require("typescript");
|
|
4
|
+
require("./ConfigLoader.js");
|
|
5
|
+
const ConfigTypes = require("./ConfigTypes.js");
|
|
6
|
+
require("reflect-metadata");
|
|
7
|
+
const ClassMemberSortingRule = require("../formatters/rules/ast/ClassMemberSortingRule.js");
|
|
8
|
+
const FileDeclarationSortingRule = require("../formatters/rules/ast/FileDeclarationSortingRule.js");
|
|
9
|
+
require("fs");
|
|
10
|
+
require("path");
|
|
11
|
+
require("fs/promises");
|
|
12
|
+
const types = require("../../shared/types.js");
|
|
13
|
+
class ConfigDefaults {
|
|
14
|
+
static {
|
|
15
|
+
this.DEFAULT_EXCLUDE_PATTERNS = ["node_modules/**", "dist/**", "vendor/**", "bin/**"];
|
|
16
|
+
}
|
|
17
|
+
static {
|
|
18
|
+
this.DEFAULT_INDEX_DIRECTORIES = ["src/", "packages/"];
|
|
19
|
+
}
|
|
20
|
+
static {
|
|
21
|
+
this.DEFAULT_JS_INCLUDE_PATTERNS = ["**/*.{js,ts,jsx,tsx}"];
|
|
22
|
+
}
|
|
23
|
+
static {
|
|
24
|
+
this.DEFAULT_TS_INCLUDE_PATTERNS = ["**/*.{ts,tsx}"];
|
|
25
|
+
}
|
|
26
|
+
/** Get default code style configuration */
|
|
27
|
+
static getDefaultCodeStyleConfig() {
|
|
28
|
+
return {
|
|
29
|
+
enabled: true,
|
|
30
|
+
quoteStyle: "double",
|
|
31
|
+
semicolons: "always",
|
|
32
|
+
bracketSpacing: false,
|
|
33
|
+
indentStyle: "space",
|
|
34
|
+
indentWidth: 4,
|
|
35
|
+
lineWidth: 120,
|
|
36
|
+
trailingCommas: "all",
|
|
37
|
+
arrowParens: "avoid"
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/** Get default directories for index generation */
|
|
41
|
+
static getDefaultIndexDirectories() {
|
|
42
|
+
return [...this.DEFAULT_INDEX_DIRECTORIES];
|
|
43
|
+
}
|
|
44
|
+
/** Get default index generation configuration */
|
|
45
|
+
static getDefaultIndexGenerationConfig() {
|
|
46
|
+
return {
|
|
47
|
+
enabled: true,
|
|
48
|
+
directories: this.getDefaultIndexDirectories(),
|
|
49
|
+
options: {
|
|
50
|
+
fileExtension: ".ts",
|
|
51
|
+
indexFileName: "index.ts",
|
|
52
|
+
recursive: true
|
|
53
|
+
},
|
|
54
|
+
updateMainIndex: true
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/** Get default import configuration */
|
|
58
|
+
static getDefaultImportConfig() {
|
|
59
|
+
return {
|
|
60
|
+
enabled: true,
|
|
61
|
+
sortImports: true,
|
|
62
|
+
removeUnused: true,
|
|
63
|
+
removeSideEffects: false,
|
|
64
|
+
groupImports: true,
|
|
65
|
+
groupOrder: ConfigTypes.ConfigTypes.getImportGroupOptions(),
|
|
66
|
+
separateGroups: false
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/** Get default include patterns for TypeScript files */
|
|
70
|
+
static getDefaultIncludePatterns() {
|
|
71
|
+
return [...this.DEFAULT_TS_INCLUDE_PATTERNS];
|
|
72
|
+
}
|
|
73
|
+
/** Get default exclude patterns for file processing */
|
|
74
|
+
static getDefaultExcludePatterns() {
|
|
75
|
+
return [...this.DEFAULT_EXCLUDE_PATTERNS];
|
|
76
|
+
}
|
|
77
|
+
/** Get default sorting configuration */
|
|
78
|
+
static getDefaultSortingConfig() {
|
|
79
|
+
return {
|
|
80
|
+
enabled: true,
|
|
81
|
+
classMembers: {
|
|
82
|
+
enabled: true,
|
|
83
|
+
order: ClassMemberSortingRule.DEFAULT_CLASS_ORDER,
|
|
84
|
+
groupByVisibility: false,
|
|
85
|
+
respectDependencies: true
|
|
86
|
+
},
|
|
87
|
+
reactComponents: {
|
|
88
|
+
enabled: true,
|
|
89
|
+
order: ClassMemberSortingRule.DEFAULT_CLASS_ORDER,
|
|
90
|
+
groupByVisibility: false,
|
|
91
|
+
respectDependencies: true
|
|
92
|
+
},
|
|
93
|
+
fileDeclarations: {
|
|
94
|
+
enabled: true,
|
|
95
|
+
order: FileDeclarationSortingRule.DEFAULT_FILE_ORDER,
|
|
96
|
+
respectDependencies: true
|
|
97
|
+
},
|
|
98
|
+
include: this.getDefaultIncludePatterns(),
|
|
99
|
+
exclude: this.getDefaultExcludePatterns()
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/** Get default spacing configuration */
|
|
103
|
+
static getDefaultSpacingConfig() {
|
|
104
|
+
return {
|
|
105
|
+
enabled: false,
|
|
106
|
+
betweenDeclarations: true,
|
|
107
|
+
beforeReturns: true,
|
|
108
|
+
betweenStatementTypes: true
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/** Get default package.json configuration */
|
|
112
|
+
static getDefaultPackageJsonConfig() {
|
|
113
|
+
return {
|
|
114
|
+
enabled: true,
|
|
115
|
+
customSortOrder: types.DefaultSortOptions.customSortOrder,
|
|
116
|
+
indentation: 4
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/** Get default tsconfig.json configuration */
|
|
120
|
+
static getDefaultTsConfigConfig() {
|
|
121
|
+
return {
|
|
122
|
+
enabled: true,
|
|
123
|
+
indentation: 4
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/** Get default formatter order */
|
|
127
|
+
static getDefaultFormatterOrder() {
|
|
128
|
+
return [
|
|
129
|
+
ConfigTypes.FormatterOrder.IndexGeneration,
|
|
130
|
+
ConfigTypes.FormatterOrder.CodeStyle,
|
|
131
|
+
ConfigTypes.FormatterOrder.ImportOrganization,
|
|
132
|
+
ConfigTypes.FormatterOrder.ASTTransformation,
|
|
133
|
+
ConfigTypes.FormatterOrder.Spacing
|
|
134
|
+
];
|
|
135
|
+
}
|
|
136
|
+
/** Get the complete default configuration */
|
|
137
|
+
static getDefaultConfig() {
|
|
138
|
+
return {
|
|
139
|
+
indexGeneration: this.getDefaultIndexGenerationConfig(),
|
|
140
|
+
codeStyle: this.getDefaultCodeStyleConfig(),
|
|
141
|
+
imports: this.getDefaultImportConfig(),
|
|
142
|
+
sorting: this.getDefaultSortingConfig(),
|
|
143
|
+
spacing: this.getDefaultSpacingConfig(),
|
|
144
|
+
packageJson: this.getDefaultPackageJsonConfig(),
|
|
145
|
+
tsConfig: this.getDefaultTsConfigConfig(),
|
|
146
|
+
formatterOrder: this.getDefaultFormatterOrder()
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
/** Get default include patterns for JavaScript files */
|
|
150
|
+
static getDefaultJavaScriptIncludePatterns() {
|
|
151
|
+
return [...this.DEFAULT_JS_INCLUDE_PATTERNS];
|
|
152
|
+
}
|
|
153
|
+
/** Create a configuration with all features disabled */
|
|
154
|
+
static getDisabledConfig() {
|
|
155
|
+
return {
|
|
156
|
+
indexGeneration: { enabled: false },
|
|
157
|
+
codeStyle: { enabled: false },
|
|
158
|
+
imports: { enabled: false },
|
|
159
|
+
sorting: { enabled: false },
|
|
160
|
+
spacing: { enabled: false },
|
|
161
|
+
packageJson: { enabled: false },
|
|
162
|
+
tsConfig: { enabled: false }
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/** Create a minimal configuration with only enabled features */
|
|
166
|
+
static getMinimalConfig() {
|
|
167
|
+
return {
|
|
168
|
+
indexGeneration: { enabled: true },
|
|
169
|
+
codeStyle: { enabled: true },
|
|
170
|
+
imports: { enabled: true },
|
|
171
|
+
sorting: { enabled: true },
|
|
172
|
+
spacing: { enabled: false },
|
|
173
|
+
packageJson: { enabled: true },
|
|
174
|
+
tsConfig: { enabled: true }
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
exports.ConfigDefaults = ConfigDefaults;
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const ts = require("typescript");
|
|
6
|
+
const ConfigDefaults = require("./ConfigDefaults.js");
|
|
7
|
+
const ConfigMerger = require("./ConfigMerger.js");
|
|
8
|
+
const ConfigValidator = require("./ConfigValidator.js");
|
|
9
|
+
function _interopNamespaceDefault(e) {
|
|
10
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
11
|
+
if (e) {
|
|
12
|
+
for (const k in e) {
|
|
13
|
+
if (k !== "default") {
|
|
14
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
15
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: () => e[k]
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
n.default = e;
|
|
23
|
+
return Object.freeze(n);
|
|
24
|
+
}
|
|
25
|
+
const fs__namespace = /* @__PURE__ */ _interopNamespaceDefault(fs);
|
|
26
|
+
const path__namespace = /* @__PURE__ */ _interopNamespaceDefault(path);
|
|
27
|
+
const ts__namespace = /* @__PURE__ */ _interopNamespaceDefault(ts);
|
|
28
|
+
class ConfigLoader {
|
|
29
|
+
static {
|
|
30
|
+
this.CONFIG_FILE_NAME = "tsfmt.config.ts";
|
|
31
|
+
}
|
|
32
|
+
static {
|
|
33
|
+
this.configCache = /* @__PURE__ */ new Map();
|
|
34
|
+
}
|
|
35
|
+
/** Clears the configuration cache */
|
|
36
|
+
static clearCache() {
|
|
37
|
+
this.configCache.clear();
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Gets the path to the config file
|
|
41
|
+
* @param projectRoot - The root directory of the project
|
|
42
|
+
* @returns Full path to the config file
|
|
43
|
+
*/
|
|
44
|
+
static getConfigFilePath(projectRoot = process.cwd()) {
|
|
45
|
+
return path__namespace.join(projectRoot, this.CONFIG_FILE_NAME);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Creates a sample configuration file
|
|
49
|
+
* @param projectRoot - The root directory of the project
|
|
50
|
+
* @param overwrite - Whether to overwrite existing file (default: false)
|
|
51
|
+
* @throws Error if file exists and overwrite is false
|
|
52
|
+
*/
|
|
53
|
+
static createSampleConfig(projectRoot = process.cwd(), overwrite = false) {
|
|
54
|
+
const configPath = this.getConfigFilePath(projectRoot);
|
|
55
|
+
if (fs__namespace.existsSync(configPath) && !overwrite) {
|
|
56
|
+
throw new Error(`Configuration file already exists at ${configPath}. Use overwrite=true to replace it.`);
|
|
57
|
+
}
|
|
58
|
+
const sampleConfig = `/*
|
|
59
|
+
* tsfmt Configuration File
|
|
60
|
+
*
|
|
61
|
+
* This file defines the configuration for tsfmt formatting.
|
|
62
|
+
* All options are optional - defaults will be used for missing values.
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
import { CoreConfig } from "tsfmt";
|
|
66
|
+
|
|
67
|
+
const config: CoreConfig = {
|
|
68
|
+
// Enable/disable index file generation
|
|
69
|
+
indexGeneration: {
|
|
70
|
+
enabled: true,
|
|
71
|
+
directories: ConfigDefaults.getDefaultIndexDirectories(),
|
|
72
|
+
updateMainIndex: true,
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
// Code style configuration
|
|
76
|
+
codeStyle: {
|
|
77
|
+
enabled: true,
|
|
78
|
+
quoteStyle: "double",
|
|
79
|
+
semicolons: "always",
|
|
80
|
+
indentWidth: 4,
|
|
81
|
+
lineWidth: 120,
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
// Import organization
|
|
85
|
+
imports: {
|
|
86
|
+
enabled: true,
|
|
87
|
+
sortImports: true,
|
|
88
|
+
removeUnused: true,
|
|
89
|
+
groupImports: true,
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
// AST-based sorting
|
|
93
|
+
sorting: {
|
|
94
|
+
enabled: true,
|
|
95
|
+
classMembers: { enabled: true },
|
|
96
|
+
fileDeclarations: { enabled: true },
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
// Spacing rules
|
|
100
|
+
spacing: {
|
|
101
|
+
enabled: false,
|
|
102
|
+
betweenDeclarations: true,
|
|
103
|
+
beforeReturns: true,
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
// JSON file sorting
|
|
107
|
+
packageJson: { enabled: true },
|
|
108
|
+
tsConfig: { enabled: true },
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export default config;
|
|
112
|
+
`;
|
|
113
|
+
fs__namespace.writeFileSync(configPath, sampleConfig, "utf-8");
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Gets cache statistics for debugging
|
|
117
|
+
* @returns Object with cache information
|
|
118
|
+
*/
|
|
119
|
+
static getCacheStats() {
|
|
120
|
+
return {
|
|
121
|
+
size: this.configCache.size,
|
|
122
|
+
keys: Array.from(this.configCache.keys())
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Gets file modification time for cache invalidation
|
|
127
|
+
* @param filePath - Path to the file
|
|
128
|
+
* @returns File modification time in milliseconds
|
|
129
|
+
*/
|
|
130
|
+
static getFileModTime(filePath) {
|
|
131
|
+
try {
|
|
132
|
+
return fs__namespace.statSync(filePath).mtime.getTime();
|
|
133
|
+
} catch {
|
|
134
|
+
return 0;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Checks if a tsfmt.config.ts file exists in the project
|
|
139
|
+
* @param projectRoot - The root directory of the project (defaults to current working directory)
|
|
140
|
+
* @returns true if tsfmt.config.ts exists
|
|
141
|
+
*/
|
|
142
|
+
static hasConfigFile(projectRoot = process.cwd()) {
|
|
143
|
+
const configPath = path__namespace.join(projectRoot, this.CONFIG_FILE_NAME);
|
|
144
|
+
return fs__namespace.existsSync(configPath);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Transpiles TypeScript code to JavaScript
|
|
148
|
+
* @param code - TypeScript code to transpile
|
|
149
|
+
* @returns Transpiled JavaScript code
|
|
150
|
+
*/
|
|
151
|
+
static transpileTypeScript(code) {
|
|
152
|
+
const result = ts__namespace.transpileModule(code, {
|
|
153
|
+
compilerOptions: {
|
|
154
|
+
module: ts__namespace.ModuleKind.CommonJS,
|
|
155
|
+
target: ts__namespace.ScriptTarget.ES2015,
|
|
156
|
+
esModuleInterop: true,
|
|
157
|
+
allowSyntheticDefaultImports: true
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
return result.outputText;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Loads and evaluates a TypeScript config file
|
|
164
|
+
* @param filePath - Path to the config file
|
|
165
|
+
* @returns Partial configuration from the file
|
|
166
|
+
* @throws Error if the config file is invalid
|
|
167
|
+
*/
|
|
168
|
+
static loadTypeScriptConfig(filePath) {
|
|
169
|
+
try {
|
|
170
|
+
const code = fs__namespace.readFileSync(filePath, "utf-8");
|
|
171
|
+
const transpiled = this.transpileTypeScript(code);
|
|
172
|
+
const module2 = { exports: {} };
|
|
173
|
+
const exports$1 = module2.exports;
|
|
174
|
+
const requireFunc = (moduleName) => {
|
|
175
|
+
if (moduleName.startsWith(".")) {
|
|
176
|
+
const resolvedPath = path__namespace.resolve(path__namespace.dirname(filePath), moduleName);
|
|
177
|
+
return require(resolvedPath);
|
|
178
|
+
}
|
|
179
|
+
return require(moduleName);
|
|
180
|
+
};
|
|
181
|
+
const func = new Function("exports", "module", "require", "__filename", "__dirname", transpiled);
|
|
182
|
+
func(exports$1, module2, requireFunc, filePath, path__namespace.dirname(filePath));
|
|
183
|
+
const config = module2.exports.default || module2.exports;
|
|
184
|
+
if (typeof config !== "object" || config === null) {
|
|
185
|
+
throw new Error(`${this.CONFIG_FILE_NAME} must export a configuration object. Found: ${typeof config}`);
|
|
186
|
+
}
|
|
187
|
+
return config;
|
|
188
|
+
} catch (error) {
|
|
189
|
+
throw new Error(`Failed to load ${this.CONFIG_FILE_NAME}: ${error instanceof Error ? error.message : String(error)}`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Loads the configuration from cache if valid, otherwise from file
|
|
194
|
+
* @param filePath - Path to the config file
|
|
195
|
+
* @returns Loaded configuration
|
|
196
|
+
*/
|
|
197
|
+
static loadConfigWithCache(filePath) {
|
|
198
|
+
const currentMtime = this.getFileModTime(filePath);
|
|
199
|
+
const cached = this.configCache.get(filePath);
|
|
200
|
+
if (cached && cached.mtime === currentMtime) {
|
|
201
|
+
return cached.config;
|
|
202
|
+
}
|
|
203
|
+
const config = this.loadTypeScriptConfig(filePath);
|
|
204
|
+
this.configCache.set(filePath, { config, mtime: currentMtime });
|
|
205
|
+
return config;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Loads the configuration from tsfmt.config.ts if it exists, otherwise returns default config
|
|
209
|
+
* @param projectRoot - The root directory of the project (defaults to current working directory)
|
|
210
|
+
* @param validate - Whether to validate the configuration (default: true)
|
|
211
|
+
* @returns The merged configuration
|
|
212
|
+
*/
|
|
213
|
+
static loadConfig(projectRoot = process.cwd(), validate = true) {
|
|
214
|
+
const configPath = this.getConfigFilePath(projectRoot);
|
|
215
|
+
if (!fs__namespace.existsSync(configPath)) {
|
|
216
|
+
return ConfigDefaults.ConfigDefaults.getDefaultConfig();
|
|
217
|
+
}
|
|
218
|
+
try {
|
|
219
|
+
const userConfig = this.loadConfigWithCache(configPath);
|
|
220
|
+
const mergedConfig = ConfigMerger.ConfigMerger.merge(userConfig);
|
|
221
|
+
if (validate) {
|
|
222
|
+
ConfigValidator.ConfigValidator.validateOrThrow(mergedConfig);
|
|
223
|
+
}
|
|
224
|
+
return mergedConfig;
|
|
225
|
+
} catch (error) {
|
|
226
|
+
console.error(`Error loading configuration from ${configPath}:`);
|
|
227
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
228
|
+
console.error("Falling back to default configuration.");
|
|
229
|
+
return ConfigDefaults.ConfigDefaults.getDefaultConfig();
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Loads configuration without validation (for debugging or inspection)
|
|
234
|
+
* @param projectRoot - The root directory of the project
|
|
235
|
+
* @returns The merged configuration without validation
|
|
236
|
+
*/
|
|
237
|
+
static loadConfigWithoutValidation(projectRoot = process.cwd()) {
|
|
238
|
+
return this.loadConfig(projectRoot, false);
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Reloads configuration by clearing cache and loading fresh
|
|
242
|
+
* @param projectRoot - The root directory of the project
|
|
243
|
+
* @returns The reloaded configuration
|
|
244
|
+
*/
|
|
245
|
+
static reloadConfig(projectRoot = process.cwd()) {
|
|
246
|
+
const configPath = this.getConfigFilePath(projectRoot);
|
|
247
|
+
this.configCache.delete(configPath);
|
|
248
|
+
return this.loadConfig(projectRoot);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
exports.ConfigLoader = ConfigLoader;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const ConfigDefaults = require("./ConfigDefaults.js");
|
|
4
|
+
class ConfigMerger {
|
|
5
|
+
/**
|
|
6
|
+
* Deep merge two configuration objects
|
|
7
|
+
* @param target - Target configuration (defaults)
|
|
8
|
+
* @param source - Source configuration (user overrides)
|
|
9
|
+
* @returns Merged configuration
|
|
10
|
+
*/
|
|
11
|
+
static deepMerge(target, source) {
|
|
12
|
+
const result = { ...target };
|
|
13
|
+
for (const key in source) {
|
|
14
|
+
if (source[key] !== void 0) {
|
|
15
|
+
if (typeof source[key] === "object" && source[key] !== null && !Array.isArray(source[key]) && typeof result[key] === "object" && result[key] !== null && !Array.isArray(result[key])) {
|
|
16
|
+
result[key] = this.deepMerge(result[key], source[key]);
|
|
17
|
+
} else {
|
|
18
|
+
result[key] = source[key];
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return result;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Merge user config with default config
|
|
26
|
+
* @param userConfig - Partial user configuration
|
|
27
|
+
* @returns Complete merged configuration
|
|
28
|
+
*/
|
|
29
|
+
static merge(userConfig) {
|
|
30
|
+
return this.deepMerge(ConfigDefaults.ConfigDefaults.getDefaultConfig(), userConfig);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Merge multiple partial configs together
|
|
34
|
+
* @param configs - Array of partial configurations to merge
|
|
35
|
+
* @returns Merged configuration
|
|
36
|
+
*/
|
|
37
|
+
static mergeMultiple(...configs) {
|
|
38
|
+
let result = ConfigDefaults.ConfigDefaults.getDefaultConfig();
|
|
39
|
+
for (const config of configs) {
|
|
40
|
+
result = this.deepMerge(result, config);
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.ConfigMerger = ConfigMerger;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
var FormatterOrder = /* @__PURE__ */ ((FormatterOrder2) => {
|
|
4
|
+
FormatterOrder2["IndexGeneration"] = "IndexGeneration";
|
|
5
|
+
FormatterOrder2["CodeStyle"] = "CodeStyle";
|
|
6
|
+
FormatterOrder2["ImportOrganization"] = "ImportOrganization";
|
|
7
|
+
FormatterOrder2["ASTTransformation"] = "ASTTransformation";
|
|
8
|
+
FormatterOrder2["Spacing"] = "Spacing";
|
|
9
|
+
return FormatterOrder2;
|
|
10
|
+
})(FormatterOrder || {});
|
|
11
|
+
class ConfigTypes {
|
|
12
|
+
/** Get all available arrow parentheses options */
|
|
13
|
+
static getArrowParenOptions() {
|
|
14
|
+
return ["always", "avoid"];
|
|
15
|
+
}
|
|
16
|
+
/** Get all formatter order options */
|
|
17
|
+
static getFormatterOrderOptions() {
|
|
18
|
+
return Object.values(FormatterOrder);
|
|
19
|
+
}
|
|
20
|
+
/** Get all available import group options */
|
|
21
|
+
static getImportGroupOptions() {
|
|
22
|
+
return ["external", "internal", "relative"];
|
|
23
|
+
}
|
|
24
|
+
/** Get all available indent style options */
|
|
25
|
+
static getIndentStyleOptions() {
|
|
26
|
+
return ["tab", "space"];
|
|
27
|
+
}
|
|
28
|
+
/** Get all available quote style options */
|
|
29
|
+
static getQuoteStyleOptions() {
|
|
30
|
+
return ["single", "double"];
|
|
31
|
+
}
|
|
32
|
+
/** Get all available semicolon options */
|
|
33
|
+
static getSemicolonOptions() {
|
|
34
|
+
return ["always", "never"];
|
|
35
|
+
}
|
|
36
|
+
/** Get all available trailing comma options */
|
|
37
|
+
static getTrailingCommaOptions() {
|
|
38
|
+
return ["none", "es5", "all"];
|
|
39
|
+
}
|
|
40
|
+
/** Check if a line width is in recommended range */
|
|
41
|
+
static isRecommendedLineWidth(width) {
|
|
42
|
+
return width >= 80 && width <= 120;
|
|
43
|
+
}
|
|
44
|
+
/** Validate an arrow parentheses option */
|
|
45
|
+
static isValidArrowParenOption(option) {
|
|
46
|
+
return this.getArrowParenOptions().includes(option);
|
|
47
|
+
}
|
|
48
|
+
/** Validate an indent style option */
|
|
49
|
+
static isValidIndentStyle(style) {
|
|
50
|
+
return this.getIndentStyleOptions().includes(style);
|
|
51
|
+
}
|
|
52
|
+
/** Check if an indent width is valid */
|
|
53
|
+
static isValidIndentWidth(width) {
|
|
54
|
+
return width >= 1 && width <= 8;
|
|
55
|
+
}
|
|
56
|
+
/** Validate a quote style option */
|
|
57
|
+
static isValidQuoteStyle(style) {
|
|
58
|
+
return this.getQuoteStyleOptions().includes(style);
|
|
59
|
+
}
|
|
60
|
+
/** Validate a semicolon option */
|
|
61
|
+
static isValidSemicolonOption(option) {
|
|
62
|
+
return this.getSemicolonOptions().includes(option);
|
|
63
|
+
}
|
|
64
|
+
/** Validate a trailing comma option */
|
|
65
|
+
static isValidTrailingCommaOption(option) {
|
|
66
|
+
return this.getTrailingCommaOptions().includes(option);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.ConfigTypes = ConfigTypes;
|
|
70
|
+
exports.FormatterOrder = FormatterOrder;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const ConfigTypes = require("./ConfigTypes.js");
|
|
4
|
+
class ConfigValidator {
|
|
5
|
+
/**
|
|
6
|
+
* Validate a CoreConfig object
|
|
7
|
+
* @param config - Configuration to validate
|
|
8
|
+
* @returns Validation result with errors and warnings
|
|
9
|
+
*/
|
|
10
|
+
static validate(config) {
|
|
11
|
+
const errors = [];
|
|
12
|
+
const warnings = [];
|
|
13
|
+
if (config.codeStyle) {
|
|
14
|
+
if (config.codeStyle.enabled && config.codeStyle.quoteStyle) {
|
|
15
|
+
if (!ConfigTypes.ConfigTypes.isValidQuoteStyle(config.codeStyle.quoteStyle)) {
|
|
16
|
+
errors.push(`Invalid quoteStyle: ${config.codeStyle.quoteStyle}. Must be ${ConfigTypes.ConfigTypes.getQuoteStyleOptions().map((s) => `'${s}'`).join(" or ")}.`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if (config.codeStyle.enabled && config.codeStyle.semicolons) {
|
|
20
|
+
if (!ConfigTypes.ConfigTypes.isValidSemicolonOption(config.codeStyle.semicolons)) {
|
|
21
|
+
errors.push(`Invalid semicolons: ${config.codeStyle.semicolons}. Must be ${ConfigTypes.ConfigTypes.getSemicolonOptions().map((s) => `'${s}'`).join(" or ")}.`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (config.codeStyle.indentWidth !== void 0) {
|
|
25
|
+
if (!ConfigTypes.ConfigTypes.isValidIndentWidth(config.codeStyle.indentWidth)) {
|
|
26
|
+
errors.push(`Invalid indentWidth: ${config.codeStyle.indentWidth}. Must be between 1 and 8.`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (config.codeStyle.lineWidth !== void 0) {
|
|
30
|
+
if (config.codeStyle.lineWidth < 40 || config.codeStyle.lineWidth > 200) {
|
|
31
|
+
if (!ConfigTypes.ConfigTypes.isRecommendedLineWidth(config.codeStyle.lineWidth)) {
|
|
32
|
+
warnings.push(`Unusual lineWidth: ${config.codeStyle.lineWidth}. Recommended range is 80-120.`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (config.imports) {
|
|
38
|
+
if (config.imports.groupOrder && config.imports.groupOrder.length > 0) {
|
|
39
|
+
const validGroups = ConfigTypes.ConfigTypes.getImportGroupOptions();
|
|
40
|
+
const invalidGroups = config.imports.groupOrder.filter((g) => !validGroups.includes(g));
|
|
41
|
+
if (invalidGroups.length > 0) {
|
|
42
|
+
errors.push(`Invalid group in groupOrder: ${invalidGroups.join(", ")}. Valid groups: ${validGroups.join(", ")}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (config.sorting) {
|
|
47
|
+
if (config.sorting.include && config.sorting.include.length === 0) {
|
|
48
|
+
warnings.push("Sorting include patterns is empty - no files will be sorted.");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
valid: errors.length === 0,
|
|
53
|
+
errors,
|
|
54
|
+
warnings
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Validate and throw if invalid
|
|
59
|
+
* @param config - Configuration to validate
|
|
60
|
+
* @throws Error if configuration is invalid
|
|
61
|
+
*/
|
|
62
|
+
static validateOrThrow(config) {
|
|
63
|
+
const result = this.validate(config);
|
|
64
|
+
if (!result.valid) {
|
|
65
|
+
throw new Error(`Invalid configuration:
|
|
66
|
+
${result.errors.join("\n")}`);
|
|
67
|
+
}
|
|
68
|
+
if (result.warnings.length > 0) {
|
|
69
|
+
console.warn("Configuration warnings:");
|
|
70
|
+
result.warnings.forEach((warning) => console.warn(` - ${warning}`));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
exports.ConfigValidator = ConfigValidator;
|