ts-ag 1.0.21 → 1.0.23

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.
@@ -5,6 +5,7 @@ import { dirname, join, resolve, relative } from 'path';
5
5
  import { parseArgs } from 'util';
6
6
  import { watch } from 'chokidar';
7
7
  import { getTsconfig } from 'get-tsconfig';
8
+ import { format as formatWithOxfmt } from 'oxfmt';
8
9
  import { colorText } from '../utils/cli.js';
9
10
  const DEFAULT_TEST_EXCLUDES = [
10
11
  '**/*.test.ts',
@@ -73,7 +74,33 @@ function computeExtraExcludes(config) {
73
74
  }
74
75
  return uniq(extra);
75
76
  }
76
- function writeBuildTsconfig(tsconfigPath, config, dryRun) {
77
+ function withTrailingNewline(value) {
78
+ return value.endsWith('\n') ? value : `${value}\n`;
79
+ }
80
+ async function formatBuildTsconfigJson(config) {
81
+ const fallback = JSON.stringify(config, null, 2);
82
+ try {
83
+ const result = await formatWithOxfmt('tsconfig.build.json', fallback, {
84
+ useTabs: false,
85
+ singleQuote: true,
86
+ trailingComma: 'none',
87
+ printWidth: 120,
88
+ objectWrap: 'collapse',
89
+ semi: true,
90
+ proseWrap: 'always',
91
+ sortPackageJson: { sortScripts: true },
92
+ sortImports: {}
93
+ });
94
+ if (!result.errors.length && typeof result.code === 'string' && result.code.length > 0) {
95
+ return withTrailingNewline(result.code);
96
+ }
97
+ }
98
+ catch {
99
+ // Fallback to plain JSON below.
100
+ }
101
+ return withTrailingNewline(fallback);
102
+ }
103
+ async function writeBuildTsconfig(tsconfigPath, config, dryRun) {
77
104
  const dir = dirname(tsconfigPath);
78
105
  const outPath = join(dir, 'tsconfig.build.json');
79
106
  const existingExclude = asArray(config.exclude);
@@ -93,7 +120,8 @@ function writeBuildTsconfig(tsconfigPath, config, dryRun) {
93
120
  // If you want to force them, do it in the base tsconfig.json or pass flags later.
94
121
  if (!dryRun) {
95
122
  mkdirSync(dir, { recursive: true });
96
- writeFileSync(outPath, `${GENERATED_FILE_HEADER}\n${JSON.stringify(buildConfig, null, 2)}\n`, 'utf8');
123
+ const formattedJson = await formatBuildTsconfigJson(buildConfig);
124
+ writeFileSync(outPath, `${GENERATED_FILE_HEADER}\n${formattedJson}`, 'utf8');
97
125
  }
98
126
  return outPath;
99
127
  }
@@ -172,7 +200,7 @@ function replaceRefsWithBuildConfigs(tsconfigPath, config, buildConfigSet) {
172
200
  });
173
201
  return { ...config, references: mapped };
174
202
  }
175
- function generateBuildConfigs(entry, options) {
203
+ async function generateBuildConfigs(entry, options) {
176
204
  const { dryRun, force, verbose } = options;
177
205
  const loadedConfigs = new Map();
178
206
  const visited = new Set();
@@ -212,7 +240,7 @@ function generateBuildConfigs(entry, options) {
212
240
  }
213
241
  else {
214
242
  const rewrittenCfg = replaceRefsWithBuildConfigs(tsconfigPath, cfg, buildConfigSet);
215
- const written = writeBuildTsconfig(tsconfigPath, rewrittenCfg, dryRun);
243
+ const written = await writeBuildTsconfig(tsconfigPath, rewrittenCfg, dryRun);
216
244
  created.push({ src: tsconfigPath, out: written });
217
245
  if (verbose || dryRun) {
218
246
  const verb = dryRun ? colorText('yellow', '[dry-run] write') : colorText('green', 'write');
@@ -247,7 +275,7 @@ function createRegenerator(entry, options) {
247
275
  logInfo(`${colorText('cyan', 'regenerate')} (${reason})`);
248
276
  reason = undefined;
249
277
  }
250
- const result = generateBuildConfigs(entry, options);
278
+ const result = await generateBuildConfigs(entry, options);
251
279
  watchedConfigs = new Set(result.visitedConfigs);
252
280
  } while (rerunRequested);
253
281
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-ag",
3
- "version": "1.0.21",
3
+ "version": "1.0.23",
4
4
  "description": "Useful TS stuff",
5
5
  "bugs": "https://github.com/ageorgeh/ts-ag/issues",
6
6
  "author": "Alexander Hornung",
@@ -57,6 +57,7 @@
57
57
  "glob": "^13.0.6",
58
58
  "jose": "6.1.3",
59
59
  "neverthrow": "8.2.0",
60
+ "oxfmt": "^0.35.0",
60
61
  "radash": "^12.1.1",
61
62
  "rehype-parse": "9.0.1",
62
63
  "tsc-alias": "1.8.16",
@@ -70,13 +71,12 @@
70
71
  "@types/hast": "3.0.4",
71
72
  "@types/node": "^24.11.0",
72
73
  "@types/ungap__structured-clone": "1.2.0",
73
- "@typescript/native-preview": "7.0.0-dev.20260227.1",
74
+ "@typescript/native-preview": "7.0.0-dev.20260228.1",
74
75
  "concurrently": "^9.2.1",
75
76
  "globals": "^17.3.0",
76
77
  "husky": "^9.1.7",
77
78
  "jiti": "2.6.1",
78
79
  "lint-staged": "^16.2.7",
79
- "oxfmt": "^0.35.0",
80
80
  "oxlint": "^1.50.0",
81
81
  "semantic-release": "^25.0.3",
82
82
  "typescript": "^5.9.3",
@@ -8,9 +8,12 @@ import { parseArgs } from 'util';
8
8
  import type { FSWatcher } from 'chokidar';
9
9
  import { watch } from 'chokidar';
10
10
  import { getTsconfig } from 'get-tsconfig';
11
+ import { format as formatWithOxfmt } from 'oxfmt';
11
12
 
12
13
  import { colorText } from '../utils/cli.js';
13
14
 
15
+ // TODO on startup check cwd for oxfmt config and use that instead of my default
16
+
14
17
  type TsConfigJson = Record<string, any>;
15
18
 
16
19
  const DEFAULT_TEST_EXCLUDES = [
@@ -91,7 +94,36 @@ function computeExtraExcludes(config: TsConfigJson): string[] {
91
94
  return uniq(extra);
92
95
  }
93
96
 
94
- function writeBuildTsconfig(tsconfigPath: string, config: TsConfigJson, dryRun: boolean): string {
97
+ function withTrailingNewline(value: string): string {
98
+ return value.endsWith('\n') ? value : `${value}\n`;
99
+ }
100
+
101
+ async function formatBuildTsconfigJson(config: TsConfigJson): Promise<string> {
102
+ const fallback = JSON.stringify(config, null, 2);
103
+
104
+ try {
105
+ const result = await formatWithOxfmt('tsconfig.build.json', fallback, {
106
+ useTabs: false,
107
+ singleQuote: true,
108
+ trailingComma: 'none',
109
+ printWidth: 120,
110
+ objectWrap: 'collapse',
111
+ semi: true,
112
+ proseWrap: 'always',
113
+ sortPackageJson: { sortScripts: true },
114
+ sortImports: {}
115
+ });
116
+ if (!result.errors.length && typeof result.code === 'string' && result.code.length > 0) {
117
+ return withTrailingNewline(result.code);
118
+ }
119
+ } catch {
120
+ // Fallback to plain JSON below.
121
+ }
122
+
123
+ return withTrailingNewline(fallback);
124
+ }
125
+
126
+ async function writeBuildTsconfig(tsconfigPath: string, config: TsConfigJson, dryRun: boolean): Promise<string> {
95
127
  const dir = dirname(tsconfigPath);
96
128
  const outPath = join(dir, 'tsconfig.build.json');
97
129
 
@@ -116,7 +148,8 @@ function writeBuildTsconfig(tsconfigPath: string, config: TsConfigJson, dryRun:
116
148
 
117
149
  if (!dryRun) {
118
150
  mkdirSync(dir, { recursive: true });
119
- writeFileSync(outPath, `${GENERATED_FILE_HEADER}\n${JSON.stringify(buildConfig, null, 2)}\n`, 'utf8');
151
+ const formattedJson = await formatBuildTsconfigJson(buildConfig);
152
+ writeFileSync(outPath, `${GENERATED_FILE_HEADER}\n${formattedJson}`, 'utf8');
120
153
  }
121
154
 
122
155
  return outPath;
@@ -207,10 +240,10 @@ function replaceRefsWithBuildConfigs(
207
240
 
208
241
  type GenerateOptions = { dryRun: boolean; force: boolean; verbose: boolean };
209
242
 
210
- function generateBuildConfigs(
243
+ async function generateBuildConfigs(
211
244
  entry: string,
212
245
  options: GenerateOptions
213
- ): { created: { src: string; out: string }[]; visitedConfigs: string[] } {
246
+ ): Promise<{ created: { src: string; out: string }[]; visitedConfigs: string[] }> {
214
247
  const { dryRun, force, verbose } = options;
215
248
 
216
249
  const loadedConfigs = new Map<string, TsConfigJson>();
@@ -251,7 +284,7 @@ function generateBuildConfigs(
251
284
  }
252
285
  } else {
253
286
  const rewrittenCfg = replaceRefsWithBuildConfigs(tsconfigPath, cfg, buildConfigSet);
254
- const written = writeBuildTsconfig(tsconfigPath, rewrittenCfg, dryRun);
287
+ const written = await writeBuildTsconfig(tsconfigPath, rewrittenCfg, dryRun);
255
288
  created.push({ src: tsconfigPath, out: written });
256
289
  if (verbose || dryRun) {
257
290
  const verb = dryRun ? colorText('yellow', '[dry-run] write') : colorText('green', 'write');
@@ -294,7 +327,7 @@ function createRegenerator(
294
327
  logInfo(`${colorText('cyan', 'regenerate')} (${reason})`);
295
328
  reason = undefined;
296
329
  }
297
- const result = generateBuildConfigs(entry, options);
330
+ const result = await generateBuildConfigs(entry, options);
298
331
  watchedConfigs = new Set(result.visitedConfigs);
299
332
  } while (rerunRequested);
300
333
  } finally {