ts-codemod-lib 1.3.1 → 1.4.0-alpha.2
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 +11 -2
- package/dist/cmd/append-as-const.d.mts.map +1 -1
- package/dist/cmd/append-as-const.mjs +19 -103
- package/dist/cmd/append-as-const.mjs.map +1 -1
- package/dist/cmd/convert-interface-to-type.d.mts.map +1 -1
- package/dist/cmd/convert-interface-to-type.mjs +19 -103
- package/dist/cmd/convert-interface-to-type.mjs.map +1 -1
- package/dist/cmd/convert-to-readonly.d.mts.map +1 -1
- package/dist/cmd/convert-to-readonly.mjs +19 -103
- package/dist/cmd/convert-to-readonly.mjs.map +1 -1
- package/dist/cmd/replace-any-with-unknown.d.mts.map +1 -1
- package/dist/cmd/replace-any-with-unknown.mjs +19 -103
- package/dist/cmd/replace-any-with-unknown.mjs.map +1 -1
- package/dist/cmd/replace-record-with-unknown-record.d.mts.map +1 -1
- package/dist/cmd/replace-record-with-unknown-record.mjs +19 -103
- package/dist/cmd/replace-record-with-unknown-record.mjs.map +1 -1
- package/dist/cmd/run-transformer-cli.d.mts +12 -0
- package/dist/cmd/run-transformer-cli.d.mts.map +1 -0
- package/dist/cmd/run-transformer-cli.mjs +146 -0
- package/dist/cmd/run-transformer-cli.mjs.map +1 -0
- package/package.json +6 -6
- package/src/cmd/append-as-const.mts +25 -163
- package/src/cmd/convert-interface-to-type.mts +25 -163
- package/src/cmd/convert-to-readonly.mts +25 -163
- package/src/cmd/replace-any-with-unknown.mts +25 -163
- package/src/cmd/replace-record-with-unknown-record.mts +25 -163
- package/src/cmd/run-transformer-cli.mts +280 -0
package/README.md
CHANGED
|
@@ -41,6 +41,13 @@ This library provides TypeScript AST transformers that can be used to automatica
|
|
|
41
41
|
|
|
42
42
|
Appends `as const` to array literals and object literals to make them readonly constants. This transformer helps in creating immutable data structures by automatically adding the TypeScript `as const` assertion.
|
|
43
43
|
|
|
44
|
+
Options:
|
|
45
|
+
|
|
46
|
+
- `applyLevel`: `'all'` or `'avoidInFunctionArgs'` (default: `'avoidInFunctionArgs'`)
|
|
47
|
+
- `'avoidInFunctionArgs'`: Avoids adding `as const` inside function call arguments
|
|
48
|
+
- `'all'`: Applies `as const` everywhere
|
|
49
|
+
- `ignorePrefixes`: Array of string prefixes for identifiers that should not have `as const` added (default: `['mut_', '#mut_', '_mut_', 'draft']`)
|
|
50
|
+
|
|
44
51
|
Example:
|
|
45
52
|
|
|
46
53
|
```ts
|
|
@@ -61,8 +68,8 @@ Converts TypeScript type definitions to readonly types. This transformer helps i
|
|
|
61
68
|
|
|
62
69
|
Options:
|
|
63
70
|
|
|
64
|
-
- `ignorePrefixes`: Array of string prefixes for identifiers that should not be made readonly
|
|
65
|
-
- `
|
|
71
|
+
- `ignorePrefixes`: Array of string prefixes for identifiers that should not be made readonly (default: `['mut_', '#mut_', '_mut_', 'draft']`)
|
|
72
|
+
- `DeepReadonly.typeName`: Custom name for the DeepReadonly type utility (default: `"DeepReadonly"`)
|
|
66
73
|
|
|
67
74
|
Example:
|
|
68
75
|
|
|
@@ -155,6 +162,8 @@ type Data2 = UnknownRecord;
|
|
|
155
162
|
### Disabling Transformers
|
|
156
163
|
|
|
157
164
|
- Nodes on the line immediately following a `// transformer-ignore-next-line` comment will be skipped.
|
|
165
|
+
- You can specify transformer names to ignore: `// transformer-ignore-next-line append-as-const, replace-any-with-unknown`
|
|
166
|
+
- If no transformer names are specified, all transformers will be skipped.
|
|
158
167
|
- Files containing a `/* transformer-ignore */` comment will be skipped entirely.
|
|
159
168
|
|
|
160
169
|
Examples:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"append-as-const.d.mts","sourceRoot":"","sources":["../../src/cmd/append-as-const.mts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"append-as-const.d.mts","sourceRoot":"","sources":["../../src/cmd/append-as-const.mts"],"names":[],"mappings":";AAIA,OAAO,eAAe,CAAC"}
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import * as cmd from 'cmd-ts';
|
|
3
|
-
import
|
|
4
|
-
import { castMutable, Result, unknownToString } from 'ts-data-forge';
|
|
3
|
+
import { Result } from 'ts-data-forge';
|
|
5
4
|
import 'ts-repo-utils';
|
|
6
5
|
import { appendAsConstTransformer } from '../functions/ast-transformers/append-as-const.mjs';
|
|
7
6
|
import 'ts-morph';
|
|
8
7
|
import '../functions/functions/is-primitive-type-node.mjs';
|
|
9
8
|
import '../functions/ast-transformers/readonly-transformer-helpers/constants.mjs';
|
|
10
|
-
import {
|
|
9
|
+
import { runTransformerCLI } from './run-transformer-cli.mjs';
|
|
11
10
|
|
|
12
|
-
/* eslint-disable no-await-in-loop */
|
|
13
11
|
const cmdDef = cmd.command({
|
|
14
12
|
name: 'append-as-const',
|
|
15
|
-
version: '1.
|
|
13
|
+
version: '1.4.0-alpha.2',
|
|
16
14
|
args: {
|
|
17
15
|
baseDir: cmd.positional({
|
|
18
16
|
type: cmd.string,
|
|
@@ -24,6 +22,11 @@ const cmdDef = cmd.command({
|
|
|
24
22
|
type: cmd.optional(cmd.array(cmd.string)),
|
|
25
23
|
description: 'Glob patterns of files to exclude from the base directory (e.g., "src/generated/**/*.mts")',
|
|
26
24
|
}),
|
|
25
|
+
uncommitted: cmd.flag({
|
|
26
|
+
long: 'uncommitted',
|
|
27
|
+
type: cmd.optional(cmd.boolean),
|
|
28
|
+
description: 'If true, transforms only uncommitted files (untracked, modified, and staged files)',
|
|
29
|
+
}),
|
|
27
30
|
silent: cmd.flag({
|
|
28
31
|
long: 'silent',
|
|
29
32
|
type: cmd.optional(cmd.boolean),
|
|
@@ -31,108 +34,21 @@ const cmdDef = cmd.command({
|
|
|
31
34
|
}),
|
|
32
35
|
},
|
|
33
36
|
handler: (args) => {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
(async () => {
|
|
38
|
+
const result = await runTransformerCLI({
|
|
39
|
+
baseDir: args.baseDir,
|
|
40
|
+
exclude: args.exclude ?? [],
|
|
41
|
+
uncommitted: args.uncommitted ?? false,
|
|
42
|
+
silent: args.silent ?? false,
|
|
43
|
+
}, [appendAsConstTransformer()]);
|
|
44
|
+
if (Result.isErr(result)) {
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
})().catch((error) => {
|
|
39
48
|
console.error('An error occurred:', error);
|
|
40
49
|
process.exit(1);
|
|
41
50
|
});
|
|
42
51
|
},
|
|
43
52
|
});
|
|
44
|
-
const appendAsConstCLI = async (args) => {
|
|
45
|
-
const echoIfNotSilent = args.silent ? () => { } : echo;
|
|
46
|
-
const errorIfNotSilent = args.silent ? () => { } : console.error;
|
|
47
|
-
// Find all files matching the glob
|
|
48
|
-
const globResult = await glob(args.baseDir, {
|
|
49
|
-
ignore: castMutable(args.exclude),
|
|
50
|
-
});
|
|
51
|
-
if (Result.isErr(globResult)) {
|
|
52
|
-
errorIfNotSilent('Error finding files matching pattern:', globResult.value);
|
|
53
|
-
return Result.err(undefined);
|
|
54
|
-
}
|
|
55
|
-
const files = globResult.value;
|
|
56
|
-
if (files.length === 0) {
|
|
57
|
-
echoIfNotSilent('No files found matching pattern:', args.baseDir);
|
|
58
|
-
return Result.ok(undefined);
|
|
59
|
-
}
|
|
60
|
-
const { errorFiles, transformedCount, unchangedCount } = await transformFiles(files, args.silent);
|
|
61
|
-
const hr = '='.repeat(50);
|
|
62
|
-
echoIfNotSilent(dedent `
|
|
63
|
-
${hr}
|
|
64
|
-
Summary:
|
|
65
|
-
✅ Transformed: ${transformedCount}
|
|
66
|
-
⏭️ Unchanged: ${unchangedCount}
|
|
67
|
-
❌ Errors: ${errorFiles.length}
|
|
68
|
-
📊 Total: ${files.length}
|
|
69
|
-
`);
|
|
70
|
-
if (errorFiles.length > 0) {
|
|
71
|
-
echoIfNotSilent('\nFiles with errors:');
|
|
72
|
-
for (const fileName of errorFiles) {
|
|
73
|
-
echoIfNotSilent(` - ${fileName}`);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
echoIfNotSilent(hr);
|
|
77
|
-
if (errorFiles.length > 0) {
|
|
78
|
-
return Result.err(undefined);
|
|
79
|
-
}
|
|
80
|
-
return Result.ok(undefined);
|
|
81
|
-
};
|
|
82
|
-
const transformFiles = async (filePaths, silent) => {
|
|
83
|
-
let mut_transformedCount = 0;
|
|
84
|
-
let mut_unchangedCount = 0;
|
|
85
|
-
const mut_errorFiles = [];
|
|
86
|
-
for (const filePath of filePaths) {
|
|
87
|
-
const result = await transformOneFile(filePath, silent);
|
|
88
|
-
if (Result.isOk(result)) {
|
|
89
|
-
switch (result.value) {
|
|
90
|
-
case 'transformed':
|
|
91
|
-
mut_transformedCount += 1;
|
|
92
|
-
break;
|
|
93
|
-
case 'unchanged':
|
|
94
|
-
mut_unchangedCount += 1;
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
else {
|
|
99
|
-
mut_errorFiles.push(path.basename(filePath));
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return {
|
|
103
|
-
transformedCount: mut_transformedCount,
|
|
104
|
-
unchangedCount: mut_unchangedCount,
|
|
105
|
-
errorFiles: mut_errorFiles,
|
|
106
|
-
};
|
|
107
|
-
};
|
|
108
|
-
const transformOneFile = async (filePath, silent) => {
|
|
109
|
-
const echoIfNotSilent = silent ? () => { } : echo;
|
|
110
|
-
const errorIfNotSilent = silent ? () => { } : console.error;
|
|
111
|
-
const fileName = path.basename(filePath);
|
|
112
|
-
const isTsx = fileName.endsWith('.tsx') || fileName.endsWith('.jsx');
|
|
113
|
-
try {
|
|
114
|
-
const originalCode = await fs.readFile(filePath, 'utf8');
|
|
115
|
-
// Transform the code with all transformers
|
|
116
|
-
const transformedCode = transformSourceCode(originalCode, isTsx, [
|
|
117
|
-
appendAsConstTransformer(),
|
|
118
|
-
]);
|
|
119
|
-
// Check if the code was actually changed
|
|
120
|
-
if (transformedCode === originalCode) {
|
|
121
|
-
echoIfNotSilent(`⏭️ ${fileName} - no changes needed`);
|
|
122
|
-
return Result.ok('unchanged');
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
// Write back the transformed code
|
|
126
|
-
await fs.writeFile(filePath, transformedCode, 'utf8');
|
|
127
|
-
echoIfNotSilent(`✅ ${fileName} - transformed`);
|
|
128
|
-
return Result.ok('transformed');
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
catch (error) {
|
|
132
|
-
const errStr = unknownToString(error);
|
|
133
|
-
errorIfNotSilent(`❌ ${fileName} - error: ${errStr}`);
|
|
134
|
-
return Result.err(errStr);
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
53
|
await cmd.run(cmdDef, process.argv.slice(2));
|
|
138
54
|
//# sourceMappingURL=append-as-const.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"append-as-const.mjs","sources":["../../src/cmd/append-as-const.mts"],"sourcesContent":[null],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"append-as-const.mjs","sources":["../../src/cmd/append-as-const.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;AAQA,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC;AACzB,IAAA,IAAI,EAAE,iBAAiB;AACvB,IAAA,OAAO,EAAE,eAAe;AACxB,IAAA,IAAI,EAAE;AACJ,QAAA,OAAO,EAAE,GAAG,CAAC,UAAU,CAAC;YACtB,IAAI,EAAE,GAAG,CAAC,MAAM;AAChB,YAAA,WAAW,EAAE,SAAS;AACtB,YAAA,WAAW,EAAE,uDAAuD;SACrE,CAAC;AACF,QAAA,OAAO,EAAE,GAAG,CAAC,WAAW,CAAC;AACvB,YAAA,IAAI,EAAE,SAAS;AACf,YAAA,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACzC,YAAA,WAAW,EACT,4FAA4F;SAC/F,CAAC;AACF,QAAA,WAAW,EAAE,GAAG,CAAC,IAAI,CAAC;AACpB,YAAA,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC;AAC/B,YAAA,WAAW,EACT,oFAAoF;SACvF,CAAC;AACF,QAAA,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC;AACf,YAAA,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC;AAC/B,YAAA,WAAW,EAAE,sDAAsD;SACpE,CAAC;AACH,KAAA;AACD,IAAA,OAAO,EAAE,CAAC,IAAI,KAAI;QAChB,CAAC,YAA0B;AACzB,YAAA,MAAM,MAAM,GAAG,MAAM,iBAAiB,CACpC;gBACE,OAAO,EAAE,IAAI,CAAC,OAAO;AACrB,gBAAA,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE;AAC3B,gBAAA,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,KAAK;AACtC,gBAAA,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK;AAC7B,aAAA,EACD,CAAC,wBAAwB,EAAE,CAAC,CAC7B;AAED,YAAA,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE;AACxB,gBAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YACjB;QACF,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAc,KAAI;AAC5B,YAAA,OAAO,CAAC,KAAK,CAAC,oBAAoB,EAAE,KAAK,CAAC;AAE1C,YAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AACjB,QAAA,CAAC,CAAC;IACJ,CAAC;AACF,CAAA,CAAC;AAEF,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convert-interface-to-type.d.mts","sourceRoot":"","sources":["../../src/cmd/convert-interface-to-type.mts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"convert-interface-to-type.d.mts","sourceRoot":"","sources":["../../src/cmd/convert-interface-to-type.mts"],"names":[],"mappings":";AAIA,OAAO,eAAe,CAAC"}
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import * as cmd from 'cmd-ts';
|
|
3
|
-
import
|
|
4
|
-
import { castMutable, Result, unknownToString } from 'ts-data-forge';
|
|
3
|
+
import { Result } from 'ts-data-forge';
|
|
5
4
|
import 'ts-repo-utils';
|
|
6
5
|
import 'ts-morph';
|
|
7
6
|
import '../functions/functions/is-primitive-type-node.mjs';
|
|
8
7
|
import { convertInterfaceToTypeTransformer } from '../functions/ast-transformers/convert-interface-to-type.mjs';
|
|
9
8
|
import '../functions/ast-transformers/readonly-transformer-helpers/constants.mjs';
|
|
10
|
-
import {
|
|
9
|
+
import { runTransformerCLI } from './run-transformer-cli.mjs';
|
|
11
10
|
|
|
12
|
-
/* eslint-disable no-await-in-loop */
|
|
13
11
|
const cmdDef = cmd.command({
|
|
14
12
|
name: 'convert-interface-to-type',
|
|
15
|
-
version: '1.
|
|
13
|
+
version: '1.4.0-alpha.2',
|
|
16
14
|
args: {
|
|
17
15
|
baseDir: cmd.positional({
|
|
18
16
|
type: cmd.string,
|
|
@@ -24,6 +22,11 @@ const cmdDef = cmd.command({
|
|
|
24
22
|
type: cmd.optional(cmd.array(cmd.string)),
|
|
25
23
|
description: 'Glob patterns of files to exclude from the base directory (e.g., "src/generated/**/*.mts")',
|
|
26
24
|
}),
|
|
25
|
+
uncommitted: cmd.flag({
|
|
26
|
+
long: 'uncommitted',
|
|
27
|
+
type: cmd.optional(cmd.boolean),
|
|
28
|
+
description: 'If true, transforms only uncommitted files (untracked, modified, and staged files)',
|
|
29
|
+
}),
|
|
27
30
|
silent: cmd.flag({
|
|
28
31
|
long: 'silent',
|
|
29
32
|
type: cmd.optional(cmd.boolean),
|
|
@@ -31,108 +34,21 @@ const cmdDef = cmd.command({
|
|
|
31
34
|
}),
|
|
32
35
|
},
|
|
33
36
|
handler: (args) => {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
(async () => {
|
|
38
|
+
const result = await runTransformerCLI({
|
|
39
|
+
baseDir: args.baseDir,
|
|
40
|
+
exclude: args.exclude ?? [],
|
|
41
|
+
uncommitted: args.uncommitted ?? false,
|
|
42
|
+
silent: args.silent ?? false,
|
|
43
|
+
}, [convertInterfaceToTypeTransformer()]);
|
|
44
|
+
if (Result.isErr(result)) {
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
})().catch((error) => {
|
|
39
48
|
console.error('An error occurred:', error);
|
|
40
49
|
process.exit(1);
|
|
41
50
|
});
|
|
42
51
|
},
|
|
43
52
|
});
|
|
44
|
-
const convertInterfaceToTypeCLI = async (args) => {
|
|
45
|
-
const echoIfNotSilent = args.silent ? () => { } : echo;
|
|
46
|
-
const errorIfNotSilent = args.silent ? () => { } : console.error;
|
|
47
|
-
// Find all files matching the glob
|
|
48
|
-
const globResult = await glob(args.baseDir, {
|
|
49
|
-
ignore: castMutable(args.exclude),
|
|
50
|
-
});
|
|
51
|
-
if (Result.isErr(globResult)) {
|
|
52
|
-
errorIfNotSilent('Error finding files matching pattern:', globResult.value);
|
|
53
|
-
return Result.err(undefined);
|
|
54
|
-
}
|
|
55
|
-
const files = globResult.value;
|
|
56
|
-
if (files.length === 0) {
|
|
57
|
-
echoIfNotSilent('No files found matching pattern:', args.baseDir);
|
|
58
|
-
return Result.ok(undefined);
|
|
59
|
-
}
|
|
60
|
-
const { errorFiles, transformedCount, unchangedCount } = await transformFiles(files, args.silent);
|
|
61
|
-
const hr = '='.repeat(50);
|
|
62
|
-
echoIfNotSilent(dedent `
|
|
63
|
-
${hr}
|
|
64
|
-
Summary:
|
|
65
|
-
✅ Transformed: ${transformedCount}
|
|
66
|
-
⏭️ Unchanged: ${unchangedCount}
|
|
67
|
-
❌ Errors: ${errorFiles.length}
|
|
68
|
-
📊 Total: ${files.length}
|
|
69
|
-
`);
|
|
70
|
-
if (errorFiles.length > 0) {
|
|
71
|
-
echoIfNotSilent('\nFiles with errors:');
|
|
72
|
-
for (const fileName of errorFiles) {
|
|
73
|
-
echoIfNotSilent(` - ${fileName}`);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
echoIfNotSilent(hr);
|
|
77
|
-
if (errorFiles.length > 0) {
|
|
78
|
-
return Result.err(undefined);
|
|
79
|
-
}
|
|
80
|
-
return Result.ok(undefined);
|
|
81
|
-
};
|
|
82
|
-
const transformFiles = async (filePaths, silent) => {
|
|
83
|
-
let mut_transformedCount = 0;
|
|
84
|
-
let mut_unchangedCount = 0;
|
|
85
|
-
const mut_errorFiles = [];
|
|
86
|
-
for (const filePath of filePaths) {
|
|
87
|
-
const result = await transformOneFile(filePath, silent);
|
|
88
|
-
if (Result.isOk(result)) {
|
|
89
|
-
switch (result.value) {
|
|
90
|
-
case 'transformed':
|
|
91
|
-
mut_transformedCount += 1;
|
|
92
|
-
break;
|
|
93
|
-
case 'unchanged':
|
|
94
|
-
mut_unchangedCount += 1;
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
else {
|
|
99
|
-
mut_errorFiles.push(path.basename(filePath));
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return {
|
|
103
|
-
transformedCount: mut_transformedCount,
|
|
104
|
-
unchangedCount: mut_unchangedCount,
|
|
105
|
-
errorFiles: mut_errorFiles,
|
|
106
|
-
};
|
|
107
|
-
};
|
|
108
|
-
const transformOneFile = async (filePath, silent) => {
|
|
109
|
-
const echoIfNotSilent = silent ? () => { } : echo;
|
|
110
|
-
const errorIfNotSilent = silent ? () => { } : console.error;
|
|
111
|
-
const fileName = path.basename(filePath);
|
|
112
|
-
const isTsx = fileName.endsWith('.tsx') || fileName.endsWith('.jsx');
|
|
113
|
-
try {
|
|
114
|
-
const originalCode = await fs.readFile(filePath, 'utf8');
|
|
115
|
-
// Transform the code with all transformers
|
|
116
|
-
const transformedCode = transformSourceCode(originalCode, isTsx, [
|
|
117
|
-
convertInterfaceToTypeTransformer(),
|
|
118
|
-
]);
|
|
119
|
-
// Check if the code was actually changed
|
|
120
|
-
if (transformedCode === originalCode) {
|
|
121
|
-
echoIfNotSilent(`⏭️ ${fileName} - no changes needed`);
|
|
122
|
-
return Result.ok('unchanged');
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
// Write back the transformed code
|
|
126
|
-
await fs.writeFile(filePath, transformedCode, 'utf8');
|
|
127
|
-
echoIfNotSilent(`✅ ${fileName} - transformed`);
|
|
128
|
-
return Result.ok('transformed');
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
catch (error) {
|
|
132
|
-
const errStr = unknownToString(error);
|
|
133
|
-
errorIfNotSilent(`❌ ${fileName} - error: ${errStr}`);
|
|
134
|
-
return Result.err(errStr);
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
53
|
await cmd.run(cmdDef, process.argv.slice(2));
|
|
138
54
|
//# sourceMappingURL=convert-interface-to-type.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convert-interface-to-type.mjs","sources":["../../src/cmd/convert-interface-to-type.mts"],"sourcesContent":[null],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"convert-interface-to-type.mjs","sources":["../../src/cmd/convert-interface-to-type.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;AAQA,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC;AACzB,IAAA,IAAI,EAAE,2BAA2B;AACjC,IAAA,OAAO,EAAE,eAAe;AACxB,IAAA,IAAI,EAAE;AACJ,QAAA,OAAO,EAAE,GAAG,CAAC,UAAU,CAAC;YACtB,IAAI,EAAE,GAAG,CAAC,MAAM;AAChB,YAAA,WAAW,EAAE,SAAS;AACtB,YAAA,WAAW,EAAE,uDAAuD;SACrE,CAAC;AACF,QAAA,OAAO,EAAE,GAAG,CAAC,WAAW,CAAC;AACvB,YAAA,IAAI,EAAE,SAAS;AACf,YAAA,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACzC,YAAA,WAAW,EACT,4FAA4F;SAC/F,CAAC;AACF,QAAA,WAAW,EAAE,GAAG,CAAC,IAAI,CAAC;AACpB,YAAA,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC;AAC/B,YAAA,WAAW,EACT,oFAAoF;SACvF,CAAC;AACF,QAAA,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC;AACf,YAAA,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC;AAC/B,YAAA,WAAW,EAAE,sDAAsD;SACpE,CAAC;AACH,KAAA;AACD,IAAA,OAAO,EAAE,CAAC,IAAI,KAAI;QAChB,CAAC,YAA0B;AACzB,YAAA,MAAM,MAAM,GAAG,MAAM,iBAAiB,CACpC;gBACE,OAAO,EAAE,IAAI,CAAC,OAAO;AACrB,gBAAA,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE;AAC3B,gBAAA,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,KAAK;AACtC,gBAAA,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK;AAC7B,aAAA,EACD,CAAC,iCAAiC,EAAE,CAAC,CACtC;AAED,YAAA,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE;AACxB,gBAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YACjB;QACF,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAc,KAAI;AAC5B,YAAA,OAAO,CAAC,KAAK,CAAC,oBAAoB,EAAE,KAAK,CAAC;AAE1C,YAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AACjB,QAAA,CAAC,CAAC;IACJ,CAAC;AACF,CAAA,CAAC;AAEF,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convert-to-readonly.d.mts","sourceRoot":"","sources":["../../src/cmd/convert-to-readonly.mts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"convert-to-readonly.d.mts","sourceRoot":"","sources":["../../src/cmd/convert-to-readonly.mts"],"names":[],"mappings":";AAIA,OAAO,eAAe,CAAC"}
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import * as cmd from 'cmd-ts';
|
|
3
|
-
import
|
|
4
|
-
import { castMutable, Result, unknownToString } from 'ts-data-forge';
|
|
3
|
+
import { Result } from 'ts-data-forge';
|
|
5
4
|
import 'ts-repo-utils';
|
|
6
5
|
import 'ts-morph';
|
|
7
6
|
import '../functions/functions/is-primitive-type-node.mjs';
|
|
8
7
|
import { convertToReadonlyTypeTransformer } from '../functions/ast-transformers/convert-to-readonly-type.mjs';
|
|
9
8
|
import '../functions/ast-transformers/readonly-transformer-helpers/constants.mjs';
|
|
10
|
-
import {
|
|
9
|
+
import { runTransformerCLI } from './run-transformer-cli.mjs';
|
|
11
10
|
|
|
12
|
-
/* eslint-disable no-await-in-loop */
|
|
13
11
|
const cmdDef = cmd.command({
|
|
14
12
|
name: 'convert-to-readonly',
|
|
15
|
-
version: '1.
|
|
13
|
+
version: '1.4.0-alpha.2',
|
|
16
14
|
args: {
|
|
17
15
|
baseDir: cmd.positional({
|
|
18
16
|
type: cmd.string,
|
|
@@ -24,6 +22,11 @@ const cmdDef = cmd.command({
|
|
|
24
22
|
type: cmd.optional(cmd.array(cmd.string)),
|
|
25
23
|
description: 'Glob patterns of files to exclude from the base directory (e.g., "src/generated/**/*.mts")',
|
|
26
24
|
}),
|
|
25
|
+
uncommitted: cmd.flag({
|
|
26
|
+
long: 'uncommitted',
|
|
27
|
+
type: cmd.optional(cmd.boolean),
|
|
28
|
+
description: 'If true, transforms only uncommitted files (untracked, modified, and staged files)',
|
|
29
|
+
}),
|
|
27
30
|
silent: cmd.flag({
|
|
28
31
|
long: 'silent',
|
|
29
32
|
type: cmd.optional(cmd.boolean),
|
|
@@ -31,108 +34,21 @@ const cmdDef = cmd.command({
|
|
|
31
34
|
}),
|
|
32
35
|
},
|
|
33
36
|
handler: (args) => {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
(async () => {
|
|
38
|
+
const result = await runTransformerCLI({
|
|
39
|
+
baseDir: args.baseDir,
|
|
40
|
+
exclude: args.exclude ?? [],
|
|
41
|
+
uncommitted: args.uncommitted ?? false,
|
|
42
|
+
silent: args.silent ?? false,
|
|
43
|
+
}, [convertToReadonlyTypeTransformer()]);
|
|
44
|
+
if (Result.isErr(result)) {
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
})().catch((error) => {
|
|
39
48
|
console.error('An error occurred:', error);
|
|
40
49
|
process.exit(1);
|
|
41
50
|
});
|
|
42
51
|
},
|
|
43
52
|
});
|
|
44
|
-
const convertToReadonlyCLI = async (args) => {
|
|
45
|
-
const echoIfNotSilent = args.silent ? () => { } : echo;
|
|
46
|
-
const errorIfNotSilent = args.silent ? () => { } : console.error;
|
|
47
|
-
// Find all files matching the glob
|
|
48
|
-
const globResult = await glob(args.baseDir, {
|
|
49
|
-
ignore: castMutable(args.exclude),
|
|
50
|
-
});
|
|
51
|
-
if (Result.isErr(globResult)) {
|
|
52
|
-
errorIfNotSilent('Error finding files matching pattern:', globResult.value);
|
|
53
|
-
return Result.err(undefined);
|
|
54
|
-
}
|
|
55
|
-
const files = globResult.value;
|
|
56
|
-
if (files.length === 0) {
|
|
57
|
-
echoIfNotSilent('No files found matching pattern:', args.baseDir);
|
|
58
|
-
return Result.ok(undefined);
|
|
59
|
-
}
|
|
60
|
-
const { errorFiles, transformedCount, unchangedCount } = await transformFiles(files, args.silent);
|
|
61
|
-
const hr = '='.repeat(50);
|
|
62
|
-
echoIfNotSilent(dedent `
|
|
63
|
-
${hr}
|
|
64
|
-
Summary:
|
|
65
|
-
✅ Transformed: ${transformedCount}
|
|
66
|
-
⏭️ Unchanged: ${unchangedCount}
|
|
67
|
-
❌ Errors: ${errorFiles.length}
|
|
68
|
-
📊 Total: ${files.length}
|
|
69
|
-
`);
|
|
70
|
-
if (errorFiles.length > 0) {
|
|
71
|
-
echoIfNotSilent('\nFiles with errors:');
|
|
72
|
-
for (const fileName of errorFiles) {
|
|
73
|
-
echoIfNotSilent(` - ${fileName}`);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
echoIfNotSilent(hr);
|
|
77
|
-
if (errorFiles.length > 0) {
|
|
78
|
-
return Result.err(undefined);
|
|
79
|
-
}
|
|
80
|
-
return Result.ok(undefined);
|
|
81
|
-
};
|
|
82
|
-
const transformFiles = async (filePaths, silent) => {
|
|
83
|
-
let mut_transformedCount = 0;
|
|
84
|
-
let mut_unchangedCount = 0;
|
|
85
|
-
const mut_errorFiles = [];
|
|
86
|
-
for (const filePath of filePaths) {
|
|
87
|
-
const result = await transformOneFile(filePath, silent);
|
|
88
|
-
if (Result.isOk(result)) {
|
|
89
|
-
switch (result.value) {
|
|
90
|
-
case 'transformed':
|
|
91
|
-
mut_transformedCount += 1;
|
|
92
|
-
break;
|
|
93
|
-
case 'unchanged':
|
|
94
|
-
mut_unchangedCount += 1;
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
else {
|
|
99
|
-
mut_errorFiles.push(path.basename(filePath));
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return {
|
|
103
|
-
transformedCount: mut_transformedCount,
|
|
104
|
-
unchangedCount: mut_unchangedCount,
|
|
105
|
-
errorFiles: mut_errorFiles,
|
|
106
|
-
};
|
|
107
|
-
};
|
|
108
|
-
const transformOneFile = async (filePath, silent) => {
|
|
109
|
-
const echoIfNotSilent = silent ? () => { } : echo;
|
|
110
|
-
const errorIfNotSilent = silent ? () => { } : console.error;
|
|
111
|
-
const fileName = path.basename(filePath);
|
|
112
|
-
const isTsx = fileName.endsWith('.tsx') || fileName.endsWith('.jsx');
|
|
113
|
-
try {
|
|
114
|
-
const originalCode = await fs.readFile(filePath, 'utf8');
|
|
115
|
-
// Transform the code with all transformers
|
|
116
|
-
const transformedCode = transformSourceCode(originalCode, isTsx, [
|
|
117
|
-
convertToReadonlyTypeTransformer(),
|
|
118
|
-
]);
|
|
119
|
-
// Check if the code was actually changed
|
|
120
|
-
if (transformedCode === originalCode) {
|
|
121
|
-
echoIfNotSilent(`⏭️ ${fileName} - no changes needed`);
|
|
122
|
-
return Result.ok('unchanged');
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
// Write back the transformed code
|
|
126
|
-
await fs.writeFile(filePath, transformedCode, 'utf8');
|
|
127
|
-
echoIfNotSilent(`✅ ${fileName} - transformed`);
|
|
128
|
-
return Result.ok('transformed');
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
catch (error) {
|
|
132
|
-
const errStr = unknownToString(error);
|
|
133
|
-
errorIfNotSilent(`❌ ${fileName} - error: ${errStr}`);
|
|
134
|
-
return Result.err(errStr);
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
53
|
await cmd.run(cmdDef, process.argv.slice(2));
|
|
138
54
|
//# sourceMappingURL=convert-to-readonly.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convert-to-readonly.mjs","sources":["../../src/cmd/convert-to-readonly.mts"],"sourcesContent":[null],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"convert-to-readonly.mjs","sources":["../../src/cmd/convert-to-readonly.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;AAQA,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC;AACzB,IAAA,IAAI,EAAE,qBAAqB;AAC3B,IAAA,OAAO,EAAE,eAAe;AACxB,IAAA,IAAI,EAAE;AACJ,QAAA,OAAO,EAAE,GAAG,CAAC,UAAU,CAAC;YACtB,IAAI,EAAE,GAAG,CAAC,MAAM;AAChB,YAAA,WAAW,EAAE,SAAS;AACtB,YAAA,WAAW,EAAE,uDAAuD;SACrE,CAAC;AACF,QAAA,OAAO,EAAE,GAAG,CAAC,WAAW,CAAC;AACvB,YAAA,IAAI,EAAE,SAAS;AACf,YAAA,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACzC,YAAA,WAAW,EACT,4FAA4F;SAC/F,CAAC;AACF,QAAA,WAAW,EAAE,GAAG,CAAC,IAAI,CAAC;AACpB,YAAA,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC;AAC/B,YAAA,WAAW,EACT,oFAAoF;SACvF,CAAC;AACF,QAAA,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC;AACf,YAAA,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC;AAC/B,YAAA,WAAW,EAAE,sDAAsD;SACpE,CAAC;AACH,KAAA;AACD,IAAA,OAAO,EAAE,CAAC,IAAI,KAAI;QAChB,CAAC,YAA0B;AACzB,YAAA,MAAM,MAAM,GAAG,MAAM,iBAAiB,CACpC;gBACE,OAAO,EAAE,IAAI,CAAC,OAAO;AACrB,gBAAA,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE;AAC3B,gBAAA,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,KAAK;AACtC,gBAAA,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK;AAC7B,aAAA,EACD,CAAC,gCAAgC,EAAE,CAAC,CACrC;AAED,YAAA,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE;AACxB,gBAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YACjB;QACF,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAc,KAAI;AAC5B,YAAA,OAAO,CAAC,KAAK,CAAC,oBAAoB,EAAE,KAAK,CAAC;AAE1C,YAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AACjB,QAAA,CAAC,CAAC;IACJ,CAAC;AACF,CAAA,CAAC;AAEF,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replace-any-with-unknown.d.mts","sourceRoot":"","sources":["../../src/cmd/replace-any-with-unknown.mts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"replace-any-with-unknown.d.mts","sourceRoot":"","sources":["../../src/cmd/replace-any-with-unknown.mts"],"names":[],"mappings":";AAIA,OAAO,eAAe,CAAC"}
|