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.
Files changed (37) hide show
  1. package/README.md +1 -1
  2. package/dist/build-plugins/transformGenericsPlugin.js +86 -0
  3. package/dist/cli.js +174 -0
  4. package/dist/core/ast/ASTAnalyzer.js +136 -0
  5. package/dist/core/ast/ASTTransformer.js +85 -0
  6. package/dist/core/ast/DependencyResolver.js +144 -0
  7. package/dist/core/config/ConfigDefaults.js +178 -0
  8. package/dist/core/config/ConfigLoader.js +251 -0
  9. package/dist/core/config/ConfigMerger.js +45 -0
  10. package/dist/core/config/ConfigTypes.js +70 -0
  11. package/dist/core/config/ConfigValidator.js +74 -0
  12. package/dist/core/di/Container.js +175 -0
  13. package/dist/core/di/ServiceRegistration.js +38 -0
  14. package/dist/core/formatters/BaseFormattingRule.js +37 -0
  15. package/dist/core/formatters/rules/ast/ClassMemberSortingRule.js +171 -0
  16. package/dist/core/formatters/rules/ast/FileDeclarationSortingRule.js +162 -0
  17. package/dist/core/formatters/rules/imports/ImportOrganizationRule.js +196 -0
  18. package/dist/core/formatters/rules/index-generation/IndexGenerationRule.js +208 -0
  19. package/dist/core/formatters/rules/spacing/BlankLineBeforeReturnsRule.js +32 -0
  20. package/dist/core/formatters/rules/spacing/BlankLineBetweenDeclarationsRule.js +93 -0
  21. package/dist/core/formatters/rules/spacing/BlankLineBetweenStatementTypesRule.js +57 -0
  22. package/dist/core/formatters/rules/spacing/BlockSpacingRule.js +17 -0
  23. package/dist/core/formatters/rules/spacing/BracketSpacingRule.js +108 -0
  24. package/dist/core/formatters/rules/style/DocBlockCommentRule.js +19 -0
  25. package/dist/core/formatters/rules/style/IndentationRule.js +45 -0
  26. package/dist/core/formatters/rules/style/QuoteStyleRule.js +63 -0
  27. package/dist/core/formatters/rules/style/SemicolonRule.js +68 -0
  28. package/dist/core/formatters/rules/style/StructuralIndentationRule.js +250 -0
  29. package/dist/core/pipeline/FormatterPipeline.js +252 -0
  30. package/dist/formatters/package.js +29 -0
  31. package/dist/index.js +66 -0
  32. package/dist/shared/types.js +28 -0
  33. package/dist/sortPackage.js +34 -0
  34. package/dist/sortTSConfig.js +34 -0
  35. package/package.json +11 -8
  36. package/bin/ci_build.sh +0 -50
  37. 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.0.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": ">=20.0.0"
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
- "format": "node bin/cli.js",
28
+ "build": "vite build",
29
+ "dev": "tsx src/cli.ts",
30
+ "format": "node dist/cli.js",
28
31
  "test": "jest"
29
32
  },
30
- "main": "bin/cli.js",
33
+ "main": "dist/cli.js",
31
34
  "files": [
32
- "bin",
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": "./bin/cli.js"
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());