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,252 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const fs = require("fs/promises");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
require("../config/ConfigDefaults.js");
|
|
6
|
+
require("../config/ConfigLoader.js");
|
|
7
|
+
const ConfigTypes = require("../config/ConfigTypes.js");
|
|
8
|
+
function _interopNamespaceDefault(e) {
|
|
9
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
10
|
+
if (e) {
|
|
11
|
+
for (const k in e) {
|
|
12
|
+
if (k !== "default") {
|
|
13
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
14
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: () => e[k]
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
n.default = e;
|
|
22
|
+
return Object.freeze(n);
|
|
23
|
+
}
|
|
24
|
+
const fs__namespace = /* @__PURE__ */ _interopNamespaceDefault(fs);
|
|
25
|
+
const path__namespace = /* @__PURE__ */ _interopNamespaceDefault(path);
|
|
26
|
+
class FormatterError extends Error {
|
|
27
|
+
constructor(formatterName, filePath, originalError) {
|
|
28
|
+
super(`Formatter '${formatterName}' failed for file '${filePath}': ${originalError.message}`);
|
|
29
|
+
this.formatterName = formatterName;
|
|
30
|
+
this.filePath = filePath;
|
|
31
|
+
this.originalError = originalError;
|
|
32
|
+
this.name = "FormatterError";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
class FormatterPipeline {
|
|
36
|
+
constructor(config, container) {
|
|
37
|
+
this.config = config;
|
|
38
|
+
this.container = container;
|
|
39
|
+
this.rules = /* @__PURE__ */ new Map();
|
|
40
|
+
this.formatterOrder = config.formatterOrder || [
|
|
41
|
+
ConfigTypes.FormatterOrder.IndexGeneration,
|
|
42
|
+
ConfigTypes.FormatterOrder.CodeStyle,
|
|
43
|
+
ConfigTypes.FormatterOrder.ImportOrganization,
|
|
44
|
+
ConfigTypes.FormatterOrder.ASTTransformation,
|
|
45
|
+
ConfigTypes.FormatterOrder.Spacing
|
|
46
|
+
];
|
|
47
|
+
this.initializeRules();
|
|
48
|
+
}
|
|
49
|
+
/** Extract type name from call stack by reading source code */
|
|
50
|
+
extractTypeNameFromStack() {
|
|
51
|
+
const stack = new Error().stack;
|
|
52
|
+
if (!stack) {
|
|
53
|
+
throw new Error("Cannot determine type name from stack");
|
|
54
|
+
}
|
|
55
|
+
const lines = stack.split("\n");
|
|
56
|
+
for (const line of lines) {
|
|
57
|
+
if (line.includes("FormatterPipeline.extractTypeNameFromStack") || line.includes("FormatterPipeline.addRule")) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
const match = line.match(/at\s+.*\s+\((.+):(\d+):(\d+)\)/);
|
|
61
|
+
if (match) {
|
|
62
|
+
const [, filePath, lineNum] = match;
|
|
63
|
+
try {
|
|
64
|
+
const fs2 = require("fs");
|
|
65
|
+
const sourceCode = fs2.readFileSync(filePath, "utf8");
|
|
66
|
+
const sourceLines = sourceCode.split("\n");
|
|
67
|
+
const callLine = sourceLines[parseInt(lineNum) - 1];
|
|
68
|
+
const typeMatch = callLine.match(/\.addRule<([^>]+)>/);
|
|
69
|
+
if (typeMatch && typeMatch[1]) {
|
|
70
|
+
return typeMatch[1].trim();
|
|
71
|
+
}
|
|
72
|
+
} catch (error) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
throw new Error("Cannot extract type name from addRule call. Use format: addRule<RuleName>(order)");
|
|
78
|
+
}
|
|
79
|
+
/** Add a rule to the pipeline at a specific order position using magical syntax */
|
|
80
|
+
addRule(order) {
|
|
81
|
+
if (!this.rules.has(order)) {
|
|
82
|
+
this.rules.set(order, []);
|
|
83
|
+
}
|
|
84
|
+
const typeName = this.extractTypeNameFromStack();
|
|
85
|
+
const ruleInstance = this.container.resolve(typeName);
|
|
86
|
+
this.rules.get(order).push(ruleInstance);
|
|
87
|
+
}
|
|
88
|
+
/** Add a rule to the pipeline by explicit name - used by Vite build transformation */
|
|
89
|
+
// @ts-ignore - This method is called after Vite build transformation replaces addRule<T>() calls
|
|
90
|
+
addRuleByName(ruleName, order) {
|
|
91
|
+
if (!this.rules.has(order)) {
|
|
92
|
+
this.rules.set(order, []);
|
|
93
|
+
}
|
|
94
|
+
const ruleInstance = this.container.resolve(ruleName);
|
|
95
|
+
this.rules.get(order).push(ruleInstance);
|
|
96
|
+
}
|
|
97
|
+
/** Get all files in a directory recursively */
|
|
98
|
+
async getFilesRecursively(dirPath, extensions) {
|
|
99
|
+
const files = [];
|
|
100
|
+
const entries = await fs__namespace.readdir(dirPath, { withFileTypes: true });
|
|
101
|
+
for (const entry of entries) {
|
|
102
|
+
const fullPath = path__namespace.join(dirPath, entry.name);
|
|
103
|
+
if (entry.isDirectory()) {
|
|
104
|
+
if (["node_modules", ".git", "dist", "build"].includes(entry.name)) {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const subFiles = await this.getFilesRecursively(fullPath, extensions);
|
|
108
|
+
files.push(...subFiles);
|
|
109
|
+
} else if (entry.isFile()) {
|
|
110
|
+
if (extensions.some((ext) => entry.name.endsWith(ext))) {
|
|
111
|
+
files.push(fullPath);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return files;
|
|
116
|
+
}
|
|
117
|
+
/** Check if source code contains a tsfmt-ignore directive */
|
|
118
|
+
shouldIgnoreFile(source) {
|
|
119
|
+
const header = source.slice(0, 1e3);
|
|
120
|
+
return /(?:\/\/|\/\*|\*)\s*tsfmt-ignore|^\s*tsfmt-ignore\s*$/m.test(header);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Format a file using the configured formatters in sequence
|
|
124
|
+
* @param filePath - Absolute path to the file to format
|
|
125
|
+
* @param dryRun - If true, don't write changes to disk
|
|
126
|
+
* @returns Pipeline context with execution details
|
|
127
|
+
* @throws FormatterError if any formatter fails (fail-fast)
|
|
128
|
+
*/
|
|
129
|
+
async formatFile(filePath, dryRun = false) {
|
|
130
|
+
const originalSource = await fs__namespace.readFile(filePath, "utf-8");
|
|
131
|
+
if (this.shouldIgnoreFile(originalSource)) {
|
|
132
|
+
return {
|
|
133
|
+
filePath,
|
|
134
|
+
originalSource,
|
|
135
|
+
currentSource: originalSource,
|
|
136
|
+
executions: [],
|
|
137
|
+
changed: false,
|
|
138
|
+
dryRun
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
const context = {
|
|
142
|
+
filePath,
|
|
143
|
+
originalSource,
|
|
144
|
+
currentSource: originalSource,
|
|
145
|
+
executions: [],
|
|
146
|
+
changed: false,
|
|
147
|
+
dryRun
|
|
148
|
+
};
|
|
149
|
+
for (const order of this.formatterOrder) {
|
|
150
|
+
const rulesAtOrder = this.rules.get(order);
|
|
151
|
+
if (!rulesAtOrder || rulesAtOrder.length === 0) {
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
for (const rule of rulesAtOrder) {
|
|
155
|
+
const execution = {
|
|
156
|
+
formatterName: rule.name,
|
|
157
|
+
order,
|
|
158
|
+
changed: false
|
|
159
|
+
};
|
|
160
|
+
try {
|
|
161
|
+
const beforeSource = context.currentSource;
|
|
162
|
+
const afterSource = rule.apply(context.currentSource, filePath);
|
|
163
|
+
execution.changed = beforeSource !== afterSource;
|
|
164
|
+
context.currentSource = afterSource;
|
|
165
|
+
if (execution.changed) {
|
|
166
|
+
context.changed = true;
|
|
167
|
+
}
|
|
168
|
+
context.executions.push(execution);
|
|
169
|
+
} catch (error) {
|
|
170
|
+
execution.error = error;
|
|
171
|
+
context.executions.push(execution);
|
|
172
|
+
throw new FormatterError(rule.name, filePath, error);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (context.changed && !dryRun) {
|
|
177
|
+
await fs__namespace.writeFile(filePath, context.currentSource, "utf-8");
|
|
178
|
+
}
|
|
179
|
+
return context;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Format multiple files in sequence
|
|
183
|
+
* @param filePaths - Array of file paths to format
|
|
184
|
+
* @param dryRun - If true, don't write changes to disk
|
|
185
|
+
* @returns Array of pipeline contexts for each file
|
|
186
|
+
* @throws FormatterError if any formatter fails for any file
|
|
187
|
+
*/
|
|
188
|
+
async formatFiles(filePaths, dryRun = false) {
|
|
189
|
+
const results = [];
|
|
190
|
+
for (const filePath of filePaths) {
|
|
191
|
+
const context = await this.formatFile(filePath, dryRun);
|
|
192
|
+
results.push(context);
|
|
193
|
+
}
|
|
194
|
+
return results;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Format all files in a directory recursively
|
|
198
|
+
* @param dirPath - Directory path to format
|
|
199
|
+
* @param dryRun - If true, don't write changes to disk
|
|
200
|
+
* @param extensions - File extensions to include (default: .ts, .tsx, .js, .jsx)
|
|
201
|
+
* @returns Array of pipeline contexts for each file
|
|
202
|
+
*/
|
|
203
|
+
async formatDirectory(dirPath, dryRun = false, extensions = [".ts", ".tsx", ".js", ".jsx"]) {
|
|
204
|
+
const files = await this.getFilesRecursively(dirPath, extensions);
|
|
205
|
+
return this.formatFiles(files, dryRun);
|
|
206
|
+
}
|
|
207
|
+
/** Get the list of formatters in execution order */
|
|
208
|
+
getFormatterOrder() {
|
|
209
|
+
return [...this.formatterOrder];
|
|
210
|
+
}
|
|
211
|
+
/** Get all rules at a specific order position */
|
|
212
|
+
getRulesAtOrder(order) {
|
|
213
|
+
return this.rules.get(order) || [];
|
|
214
|
+
}
|
|
215
|
+
/** Check if any rules are configured */
|
|
216
|
+
hasRules() {
|
|
217
|
+
return this.rules.size > 0;
|
|
218
|
+
}
|
|
219
|
+
/** Initialize rules based on configuration using clean DI pattern */
|
|
220
|
+
initializeRules() {
|
|
221
|
+
if (this.config.indexGeneration?.enabled) {
|
|
222
|
+
this.addRuleByName("IndexGenerationRule", ConfigTypes.FormatterOrder.IndexGeneration);
|
|
223
|
+
}
|
|
224
|
+
if (this.config.codeStyle?.enabled) {
|
|
225
|
+
this.addRuleByName("QuoteStyleRule", ConfigTypes.FormatterOrder.CodeStyle);
|
|
226
|
+
this.addRuleByName("SemicolonRule", ConfigTypes.FormatterOrder.CodeStyle);
|
|
227
|
+
this.addRuleByName("BracketSpacingRule", ConfigTypes.FormatterOrder.CodeStyle);
|
|
228
|
+
this.addRuleByName("IndentationRule", ConfigTypes.FormatterOrder.CodeStyle);
|
|
229
|
+
this.addRuleByName("StructuralIndentationRule", ConfigTypes.FormatterOrder.CodeStyle);
|
|
230
|
+
this.addRuleByName("BlockSpacingRule", ConfigTypes.FormatterOrder.CodeStyle);
|
|
231
|
+
this.addRuleByName("DocBlockCommentRule", ConfigTypes.FormatterOrder.CodeStyle);
|
|
232
|
+
}
|
|
233
|
+
if (this.config.imports?.enabled) {
|
|
234
|
+
this.addRuleByName("ImportOrganizationRule", ConfigTypes.FormatterOrder.ImportOrganization);
|
|
235
|
+
}
|
|
236
|
+
if (this.config.sorting?.enabled) {
|
|
237
|
+
if (this.config.sorting.classMembers?.enabled) {
|
|
238
|
+
this.addRuleByName("ClassMemberSortingRule", ConfigTypes.FormatterOrder.ASTTransformation);
|
|
239
|
+
}
|
|
240
|
+
if (this.config.sorting.fileDeclarations?.enabled) {
|
|
241
|
+
this.addRuleByName("FileDeclarationSortingRule", ConfigTypes.FormatterOrder.ASTTransformation);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (this.config.spacing?.enabled) {
|
|
245
|
+
this.addRuleByName("BlankLineBetweenDeclarationsRule", ConfigTypes.FormatterOrder.Spacing);
|
|
246
|
+
this.addRuleByName("BlankLineBetweenStatementTypesRule", ConfigTypes.FormatterOrder.Spacing);
|
|
247
|
+
this.addRuleByName("BlankLineBeforeReturnsRule", ConfigTypes.FormatterOrder.Spacing);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
exports.FormatterError = FormatterError;
|
|
252
|
+
exports.FormatterPipeline = FormatterPipeline;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
function sortExportsKeys(exports$1) {
|
|
4
|
+
if (!exports$1 || typeof exports$1 !== "object") {
|
|
5
|
+
return exports$1;
|
|
6
|
+
}
|
|
7
|
+
const sortedExports = {};
|
|
8
|
+
const exportKeyOrder = ["types", "import", "require"];
|
|
9
|
+
for (const [key, value] of Object.entries(exports$1)) {
|
|
10
|
+
if (typeof value === "object" && value !== null) {
|
|
11
|
+
const sortedSubObject = {};
|
|
12
|
+
exportKeyOrder.forEach((subKey) => {
|
|
13
|
+
if (subKey in value) {
|
|
14
|
+
sortedSubObject[subKey] = value[subKey];
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
for (const subKey of Object.keys(value)) {
|
|
18
|
+
if (!exportKeyOrder.includes(subKey)) {
|
|
19
|
+
sortedSubObject[subKey] = value[subKey];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
sortedExports[key] = sortedSubObject;
|
|
23
|
+
} else {
|
|
24
|
+
sortedExports[key] = value;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return sortedExports;
|
|
28
|
+
}
|
|
29
|
+
exports.sortExportsKeys = sortExportsKeys;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const transformGenericsPlugin = require("./build-plugins/transformGenericsPlugin.js");
|
|
4
|
+
const ASTAnalyzer = require("./core/ast/ASTAnalyzer.js");
|
|
5
|
+
const ASTTransformer = require("./core/ast/ASTTransformer.js");
|
|
6
|
+
const DependencyResolver = require("./core/ast/DependencyResolver.js");
|
|
7
|
+
const ConfigDefaults = require("./core/config/ConfigDefaults.js");
|
|
8
|
+
const ConfigLoader = require("./core/config/ConfigLoader.js");
|
|
9
|
+
const ConfigMerger = require("./core/config/ConfigMerger.js");
|
|
10
|
+
const ConfigTypes = require("./core/config/ConfigTypes.js");
|
|
11
|
+
const ConfigValidator = require("./core/config/ConfigValidator.js");
|
|
12
|
+
const Container = require("./core/di/Container.js");
|
|
13
|
+
const ServiceRegistration = require("./core/di/ServiceRegistration.js");
|
|
14
|
+
const BaseFormattingRule = require("./core/formatters/BaseFormattingRule.js");
|
|
15
|
+
const ClassMemberSortingRule = require("./core/formatters/rules/ast/ClassMemberSortingRule.js");
|
|
16
|
+
const FileDeclarationSortingRule = require("./core/formatters/rules/ast/FileDeclarationSortingRule.js");
|
|
17
|
+
const ImportOrganizationRule = require("./core/formatters/rules/imports/ImportOrganizationRule.js");
|
|
18
|
+
const IndexGenerationRule = require("./core/formatters/rules/index-generation/IndexGenerationRule.js");
|
|
19
|
+
const BlankLineBeforeReturnsRule = require("./core/formatters/rules/spacing/BlankLineBeforeReturnsRule.js");
|
|
20
|
+
const BlankLineBetweenDeclarationsRule = require("./core/formatters/rules/spacing/BlankLineBetweenDeclarationsRule.js");
|
|
21
|
+
const BlankLineBetweenStatementTypesRule = require("./core/formatters/rules/spacing/BlankLineBetweenStatementTypesRule.js");
|
|
22
|
+
const BlockSpacingRule = require("./core/formatters/rules/spacing/BlockSpacingRule.js");
|
|
23
|
+
const BracketSpacingRule = require("./core/formatters/rules/spacing/BracketSpacingRule.js");
|
|
24
|
+
const DocBlockCommentRule = require("./core/formatters/rules/style/DocBlockCommentRule.js");
|
|
25
|
+
const IndentationRule = require("./core/formatters/rules/style/IndentationRule.js");
|
|
26
|
+
const QuoteStyleRule = require("./core/formatters/rules/style/QuoteStyleRule.js");
|
|
27
|
+
const SemicolonRule = require("./core/formatters/rules/style/SemicolonRule.js");
|
|
28
|
+
const StructuralIndentationRule = require("./core/formatters/rules/style/StructuralIndentationRule.js");
|
|
29
|
+
const FormatterPipeline = require("./core/pipeline/FormatterPipeline.js");
|
|
30
|
+
const _package = require("./formatters/package.js");
|
|
31
|
+
const types = require("./shared/types.js");
|
|
32
|
+
exports.transformGenericsPlugin = transformGenericsPlugin.transformGenericsPlugin;
|
|
33
|
+
exports.ASTAnalyzer = ASTAnalyzer.ASTAnalyzer;
|
|
34
|
+
exports.ASTTransformer = ASTTransformer.ASTTransformer;
|
|
35
|
+
exports.DependencyResolver = DependencyResolver.DependencyResolver;
|
|
36
|
+
exports.ConfigDefaults = ConfigDefaults.ConfigDefaults;
|
|
37
|
+
exports.ConfigLoader = ConfigLoader.ConfigLoader;
|
|
38
|
+
exports.ConfigMerger = ConfigMerger.ConfigMerger;
|
|
39
|
+
exports.ConfigTypes = ConfigTypes.ConfigTypes;
|
|
40
|
+
exports.FormatterOrder = ConfigTypes.FormatterOrder;
|
|
41
|
+
exports.ConfigValidator = ConfigValidator.ConfigValidator;
|
|
42
|
+
exports.Container = Container.Container;
|
|
43
|
+
exports.ServiceRegistration = ServiceRegistration.ServiceRegistration;
|
|
44
|
+
exports.BaseFormattingRule = BaseFormattingRule.BaseFormattingRule;
|
|
45
|
+
exports.ClassMemberSortingRule = ClassMemberSortingRule.ClassMemberSortingRule;
|
|
46
|
+
exports.DEFAULT_CLASS_ORDER = ClassMemberSortingRule.DEFAULT_CLASS_ORDER;
|
|
47
|
+
exports.MemberType = ClassMemberSortingRule.MemberType;
|
|
48
|
+
exports.DEFAULT_FILE_ORDER = FileDeclarationSortingRule.DEFAULT_FILE_ORDER;
|
|
49
|
+
exports.DeclarationType = FileDeclarationSortingRule.DeclarationType;
|
|
50
|
+
exports.FileDeclarationSortingRule = FileDeclarationSortingRule.FileDeclarationSortingRule;
|
|
51
|
+
exports.ImportOrganizationRule = ImportOrganizationRule.ImportOrganizationRule;
|
|
52
|
+
exports.IndexGenerationRule = IndexGenerationRule.IndexGenerationRule;
|
|
53
|
+
exports.BlankLineBeforeReturnsRule = BlankLineBeforeReturnsRule.BlankLineBeforeReturnsRule;
|
|
54
|
+
exports.BlankLineBetweenDeclarationsRule = BlankLineBetweenDeclarationsRule.BlankLineBetweenDeclarationsRule;
|
|
55
|
+
exports.BlankLineBetweenStatementTypesRule = BlankLineBetweenStatementTypesRule.BlankLineBetweenStatementTypesRule;
|
|
56
|
+
exports.BlockSpacingRule = BlockSpacingRule.BlockSpacingRule;
|
|
57
|
+
exports.BracketSpacingRule = BracketSpacingRule.BracketSpacingRule;
|
|
58
|
+
exports.DocBlockCommentRule = DocBlockCommentRule.DocBlockCommentRule;
|
|
59
|
+
exports.IndentationRule = IndentationRule.IndentationRule;
|
|
60
|
+
exports.QuoteStyleRule = QuoteStyleRule.QuoteStyleRule;
|
|
61
|
+
exports.SemicolonRule = SemicolonRule.SemicolonRule;
|
|
62
|
+
exports.StructuralIndentationRule = StructuralIndentationRule.StructuralIndentationRule;
|
|
63
|
+
exports.FormatterError = FormatterPipeline.FormatterError;
|
|
64
|
+
exports.FormatterPipeline = FormatterPipeline.FormatterPipeline;
|
|
65
|
+
exports.sortExportsKeys = _package.sortExportsKeys;
|
|
66
|
+
exports.DefaultSortOptions = types.DefaultSortOptions;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const DefaultSortOptions = {
|
|
4
|
+
customSortOrder: [
|
|
5
|
+
"name",
|
|
6
|
+
"type",
|
|
7
|
+
"author",
|
|
8
|
+
"version",
|
|
9
|
+
"description",
|
|
10
|
+
"publishConfig",
|
|
11
|
+
"keywords",
|
|
12
|
+
"homepage",
|
|
13
|
+
"engines",
|
|
14
|
+
"dependencies",
|
|
15
|
+
"devDependencies",
|
|
16
|
+
"scripts",
|
|
17
|
+
"types",
|
|
18
|
+
"main",
|
|
19
|
+
"module",
|
|
20
|
+
"exports",
|
|
21
|
+
"files",
|
|
22
|
+
"repository",
|
|
23
|
+
"bugs"
|
|
24
|
+
],
|
|
25
|
+
indentation: 4,
|
|
26
|
+
dryRun: false
|
|
27
|
+
};
|
|
28
|
+
exports.DefaultSortOptions = DefaultSortOptions;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const sortPackageJson$1 = require("sort-package-json");
|
|
6
|
+
const _package = require("./formatters/package.js");
|
|
7
|
+
const types = require("./shared/types.js");
|
|
8
|
+
function sortPackageJson(packageObj, options = {}) {
|
|
9
|
+
const sortOrder = options.customSortOrder || types.DefaultSortOptions.customSortOrder;
|
|
10
|
+
let sortedPackage = sortPackageJson$1.sortPackageJson(packageObj, {
|
|
11
|
+
sortOrder
|
|
12
|
+
});
|
|
13
|
+
if (sortedPackage.exports) {
|
|
14
|
+
sortedPackage.exports = _package.sortExportsKeys(sortedPackage.exports);
|
|
15
|
+
}
|
|
16
|
+
return sortedPackage;
|
|
17
|
+
}
|
|
18
|
+
function sortPackageFile(filePath, options = {}) {
|
|
19
|
+
const packagePath = filePath || path.join(process.cwd(), "package.json");
|
|
20
|
+
const indentation = options.indentation || types.DefaultSortOptions.indentation;
|
|
21
|
+
try {
|
|
22
|
+
const packageJson = JSON.parse(fs.readFileSync(packagePath, "utf8"));
|
|
23
|
+
const sortedPackageJson = sortPackageJson(packageJson, options);
|
|
24
|
+
if (!options.dryRun) {
|
|
25
|
+
fs.writeFileSync(packagePath, JSON.stringify(sortedPackageJson, null, indentation) + "\n");
|
|
26
|
+
}
|
|
27
|
+
return sortedPackageJson;
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.error(`Error processing ${packagePath}:`, error);
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.sortPackageFile = sortPackageFile;
|
|
34
|
+
exports.sortPackageJson = sortPackageJson;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const types = require("./shared/types.js");
|
|
6
|
+
function sortObjectKeysAlphabetically(obj) {
|
|
7
|
+
if (typeof obj !== "object" || obj === null || Array.isArray(obj)) {
|
|
8
|
+
return obj;
|
|
9
|
+
}
|
|
10
|
+
return Object.keys(obj).sort().reduce((result, key) => {
|
|
11
|
+
result[key] = sortObjectKeysAlphabetically(obj[key]);
|
|
12
|
+
return result;
|
|
13
|
+
}, {});
|
|
14
|
+
}
|
|
15
|
+
function sortTsConfig(tsConfig) {
|
|
16
|
+
return sortObjectKeysAlphabetically(tsConfig);
|
|
17
|
+
}
|
|
18
|
+
function sortTsConfigFile(filePath, options = {}) {
|
|
19
|
+
const tsConfigPath = filePath || path.join(process.cwd(), "tsconfig.json");
|
|
20
|
+
const indentation = options.indentation || types.DefaultSortOptions.indentation;
|
|
21
|
+
try {
|
|
22
|
+
const tsConfig = JSON.parse(fs.readFileSync(tsConfigPath, "utf8"));
|
|
23
|
+
const sortedTsConfig = sortTsConfig(tsConfig);
|
|
24
|
+
if (!options.dryRun) {
|
|
25
|
+
fs.writeFileSync(tsConfigPath, JSON.stringify(sortedTsConfig, null, indentation) + "\n");
|
|
26
|
+
}
|
|
27
|
+
return sortedTsConfig;
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.error(`Error processing ${tsConfigPath}:`, error);
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.sortTsConfig = sortTsConfig;
|
|
34
|
+
exports.sortTsConfigFile = sortTsConfigFile;
|
package/package.json
CHANGED
|
@@ -1,35 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tsfmt",
|
|
3
3
|
"author": "Encore Digital Group",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.1",
|
|
5
5
|
"description": "An opinionated TypeScript code formatter",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public",
|
|
8
8
|
"registry": "https://registry.npmjs.org"
|
|
9
9
|
},
|
|
10
10
|
"engines": {
|
|
11
|
-
"node": ">=
|
|
11
|
+
"node": ">=22.0.0"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"glob": "^13.0.0",
|
|
15
15
|
"json-sort-cli": "^4.0.9",
|
|
16
|
+
"reflect-metadata": "^0.2.2",
|
|
16
17
|
"sort-package-json": "^3.0.0",
|
|
17
|
-
"tsx": "^4.21.0",
|
|
18
18
|
"typescript": "^5.0.0"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@types/jest": "^30.0.0",
|
|
22
22
|
"@types/node": "^25.0.3",
|
|
23
23
|
"jest": "^30.1.1",
|
|
24
|
-
"ts-jest": "^29.0.0"
|
|
24
|
+
"ts-jest": "^29.0.0",
|
|
25
|
+
"vite": "^7.0.0"
|
|
25
26
|
},
|
|
26
27
|
"scripts": {
|
|
27
|
-
"
|
|
28
|
+
"build": "vite build",
|
|
29
|
+
"dev": "tsx src/cli.ts",
|
|
30
|
+
"format": "node dist/cli.js",
|
|
28
31
|
"test": "jest"
|
|
29
32
|
},
|
|
30
|
-
"main": "
|
|
33
|
+
"main": "dist/cli.js",
|
|
31
34
|
"files": [
|
|
32
|
-
"
|
|
35
|
+
"dist",
|
|
33
36
|
"README.md"
|
|
34
37
|
],
|
|
35
38
|
"repository": {
|
|
@@ -38,6 +41,6 @@
|
|
|
38
41
|
},
|
|
39
42
|
"license": "BSD-3-Clause",
|
|
40
43
|
"bin": {
|
|
41
|
-
"tsfmt": "./
|
|
44
|
+
"tsfmt": "./dist/cli.js"
|
|
42
45
|
}
|
|
43
46
|
}
|
package/bin/ci_build.sh
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
#
|
|
3
|
-
# Copyright (c) 2025. Encore Digital Group.
|
|
4
|
-
# All Rights Reserved.
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
git config --global user.name "EncoreBot"
|
|
8
|
-
git config --global user.email "ghbot@encoredigitalgroup.com"
|
|
9
|
-
|
|
10
|
-
# Change to workspace directory
|
|
11
|
-
cd "$GITHUB_WORKSPACE" || {
|
|
12
|
-
echo "Error: Failed to change directory to $GITHUB_WORKSPACE"
|
|
13
|
-
exit 1
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
# Run build and capture exit code
|
|
17
|
-
npm run format
|
|
18
|
-
BUILD_EXIT_CODE=$?
|
|
19
|
-
|
|
20
|
-
# If build failed, exit with the same code
|
|
21
|
-
if [ $BUILD_EXIT_CODE -ne 0 ]; then
|
|
22
|
-
echo "Build failed with exit code $BUILD_EXIT_CODE"
|
|
23
|
-
exit $BUILD_EXIT_CODE
|
|
24
|
-
fi
|
|
25
|
-
|
|
26
|
-
# Run format and capture exit code
|
|
27
|
-
npm run format
|
|
28
|
-
FORMAT_EXIT_CODE=$?
|
|
29
|
-
|
|
30
|
-
# If format failed, exit with the same code
|
|
31
|
-
if [ $FORMAT_EXIT_CODE -ne 0 ]; then
|
|
32
|
-
echo "Format failed with exit code $FORMAT_EXIT_CODE"
|
|
33
|
-
exit $FORMAT_EXIT_CODE
|
|
34
|
-
fi
|
|
35
|
-
|
|
36
|
-
# Build and format succeeded, check for changes
|
|
37
|
-
if [ -z "$(git status --porcelain)" ]; then
|
|
38
|
-
# Working directory clean
|
|
39
|
-
echo "Working Tree is Clean! Nothing to commit."
|
|
40
|
-
else
|
|
41
|
-
# Add all changes to staging
|
|
42
|
-
git add .
|
|
43
|
-
|
|
44
|
-
# Commit changes
|
|
45
|
-
commit_message="Apply Formatting"
|
|
46
|
-
git commit -m "$commit_message"
|
|
47
|
-
|
|
48
|
-
# Push changes to origin
|
|
49
|
-
git push origin --force
|
|
50
|
-
fi
|
package/bin/cli.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/*
|
|
3
|
-
* Copyright (c) 2026. Encore Digital Group.
|
|
4
|
-
* All Rights Reserved.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
// This is the entry point for consumers of the package
|
|
8
|
-
// It uses tsx to run the TypeScript source directly without requiring a build step
|
|
9
|
-
|
|
10
|
-
const { register } = require('tsx/cjs/api');
|
|
11
|
-
const path = require('path');
|
|
12
|
-
|
|
13
|
-
// Register tsx to handle TypeScript files
|
|
14
|
-
const unregister = register();
|
|
15
|
-
|
|
16
|
-
// Load and run the CLI
|
|
17
|
-
require(path.join(__dirname, '../src/cli.ts'));
|
|
18
|
-
|
|
19
|
-
// Cleanup
|
|
20
|
-
process.on('exit', () => unregister());
|