ts-codemod-lib 1.0.1 → 1.1.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 +428 -6
- package/dist/cmd/append-as-const.d.mts +3 -0
- package/dist/cmd/append-as-const.d.mts.map +1 -0
- package/dist/cmd/append-as-const.mjs +138 -0
- package/dist/cmd/append-as-const.mjs.map +1 -0
- package/dist/cmd/convert-interface-to-type.d.mts +3 -0
- package/dist/cmd/convert-interface-to-type.d.mts.map +1 -0
- package/dist/cmd/convert-interface-to-type.mjs +138 -0
- package/dist/cmd/convert-interface-to-type.mjs.map +1 -0
- package/dist/cmd/convert-to-readonly.mjs +3 -2
- package/dist/cmd/convert-to-readonly.mjs.map +1 -1
- package/dist/cmd/replace-any-with-unknown.d.mts +3 -0
- package/dist/cmd/replace-any-with-unknown.d.mts.map +1 -0
- package/dist/cmd/replace-any-with-unknown.mjs +138 -0
- package/dist/cmd/replace-any-with-unknown.mjs.map +1 -0
- package/dist/cmd/replace-record-with-unknown-record.d.mts +3 -0
- package/dist/cmd/replace-record-with-unknown-record.d.mts.map +1 -0
- package/dist/cmd/replace-record-with-unknown-record.mjs +138 -0
- package/dist/cmd/replace-record-with-unknown-record.mjs.map +1 -0
- package/dist/entry-point.mjs +2 -0
- package/dist/entry-point.mjs.map +1 -1
- package/dist/functions/ast-transformers/append-as-const.d.mts +13 -0
- package/dist/functions/ast-transformers/append-as-const.d.mts.map +1 -0
- package/dist/functions/ast-transformers/append-as-const.mjs +98 -0
- package/dist/functions/ast-transformers/append-as-const.mjs.map +1 -0
- package/dist/functions/ast-transformers/index.d.mts +2 -0
- package/dist/functions/ast-transformers/index.d.mts.map +1 -1
- package/dist/functions/ast-transformers/index.mjs +2 -0
- package/dist/functions/ast-transformers/index.mjs.map +1 -1
- package/dist/functions/ast-transformers/replace-any-with-unknown.d.mts +3 -0
- package/dist/functions/ast-transformers/replace-any-with-unknown.d.mts.map +1 -0
- package/dist/functions/ast-transformers/replace-any-with-unknown.mjs +38 -0
- package/dist/functions/ast-transformers/replace-any-with-unknown.mjs.map +1 -0
- package/dist/functions/index.mjs +2 -0
- package/dist/functions/index.mjs.map +1 -1
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +61 -57
- package/src/cmd/append-as-const.mts +197 -0
- package/src/cmd/convert-interface-to-type.mts +197 -0
- package/src/cmd/convert-to-readonly.mts +3 -1
- package/src/cmd/replace-any-with-unknown.mts +197 -0
- package/src/cmd/replace-record-with-unknown-record.mts +197 -0
- package/src/functions/ast-transformers/append-as-const.mts +154 -0
- package/src/functions/ast-transformers/append-as-const.test.mts +339 -0
- package/src/functions/ast-transformers/convert-to-readonly-type.test.mts +3 -3
- package/src/functions/ast-transformers/index.mts +2 -0
- package/src/functions/ast-transformers/replace-any-with-unknown.mts +49 -0
- package/src/functions/ast-transformers/replace-any-with-unknown.test.mts +140 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
export * from './append-as-const.mjs';
|
|
1
2
|
export * from './convert-interface-to-type.mjs';
|
|
2
3
|
export * from './convert-to-readonly-type.mjs';
|
|
3
4
|
export * from './readonly-transformer-helpers/index.mjs';
|
|
5
|
+
export * from './replace-any-with-unknown.mjs';
|
|
4
6
|
export * from './replace-record-with-unknown-record.mjs';
|
|
5
7
|
export * from './transform-source-code.mjs';
|
|
6
8
|
export * from './types.mjs';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../../src/functions/ast-transformers/index.mts"],"names":[],"mappings":"AAAA,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0CAA0C,CAAC;AACzD,cAAc,0CAA0C,CAAC;AACzD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../../src/functions/ast-transformers/index.mts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0CAA0C,CAAC;AACzD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0CAA0C,CAAC;AACzD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,aAAa,CAAC"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
export { appendAsConstTransformer } from './append-as-const.mjs';
|
|
1
2
|
export { convertInterfaceToTypeTransformer } from './convert-interface-to-type.mjs';
|
|
2
3
|
export { convertToReadonlyTypeTransformer } from './convert-to-readonly-type.mjs';
|
|
3
4
|
export { compareUnionIntersectionTypes } from './readonly-transformer-helpers/compare-union-types.mjs';
|
|
4
5
|
export { invalidDeepReadonlyTypeName } from './readonly-transformer-helpers/constants.mjs';
|
|
5
6
|
export { groupUnionIntersectionTypes } from './readonly-transformer-helpers/group-union-types.mjs';
|
|
6
7
|
export { nextReadonlyContext } from './readonly-transformer-helpers/readonly-context.mjs';
|
|
8
|
+
export { replaceAnyWithUnknownTransformer } from './replace-any-with-unknown.mjs';
|
|
7
9
|
export { replaceRecordWithUnknownRecordTransformer } from './replace-record-with-unknown-record.mjs';
|
|
8
10
|
export { transformSourceCode } from './transform-source-code.mjs';
|
|
9
11
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replace-any-with-unknown.d.mts","sourceRoot":"","sources":["../../../src/functions/ast-transformers/replace-any-with-unknown.mts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEtD,eAAO,MAAM,gCAAgC,QAAO,kBAA0B,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as tsm from 'ts-morph';
|
|
2
|
+
import { hasDisableNextLineComment } from '../functions/has-disable-next-line-comment.mjs';
|
|
3
|
+
import '../functions/is-primitive-type-node.mjs';
|
|
4
|
+
import 'ts-data-forge';
|
|
5
|
+
import { isSpreadParameterNode, isSpreadNamedTupleMemberNode } from '../functions/is-spread-parameter-node.mjs';
|
|
6
|
+
|
|
7
|
+
const replaceAnyWithUnknownTransformer = () => body;
|
|
8
|
+
const body = (sourceAst) => {
|
|
9
|
+
for (const node of sourceAst.getChildren()) {
|
|
10
|
+
transformNode(node);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
const transformNode = (node) => {
|
|
14
|
+
if (hasDisableNextLineComment(node)) {
|
|
15
|
+
console.debug('skipped by disable-next-line comment');
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (node.isKind(tsm.SyntaxKind.AnyKeyword)) {
|
|
19
|
+
const anyKeywordNode = node;
|
|
20
|
+
const parent = anyKeywordNode.getParent();
|
|
21
|
+
if (parent !== undefined &&
|
|
22
|
+
// `(...args: any) => any` -> `(...args: unknown[]) => any`
|
|
23
|
+
(isSpreadParameterNode(parent) ||
|
|
24
|
+
// `[name: E0, ...args: any)]` -> `[name: E0, ...args: unknown[]]`
|
|
25
|
+
isSpreadNamedTupleMemberNode(parent))) {
|
|
26
|
+
anyKeywordNode.replaceWithText('readonly unknown[]');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
anyKeywordNode.replaceWithText('unknown');
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
for (const child of node.getChildren()) {
|
|
33
|
+
transformNode(child);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export { replaceAnyWithUnknownTransformer };
|
|
38
|
+
//# sourceMappingURL=replace-any-with-unknown.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replace-any-with-unknown.mjs","sources":["../../../src/functions/ast-transformers/replace-any-with-unknown.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;MAQa,gCAAgC,GAAG,MAA0B;AAE1E,MAAM,IAAI,GAAuB,CAAC,SAAS,KAAI;IAC7C,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,WAAW,EAAE,EAAE;QAC1C,aAAa,CAAC,IAAI,CAAC;IACrB;AACF,CAAC;AAED,MAAM,aAAa,GAAG,CAAC,IAAc,KAAU;AAC7C,IAAA,IAAI,yBAAyB,CAAC,IAAI,CAAC,EAAE;AACnC,QAAA,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC;QAErD;IACF;IAEA,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;QAC1C,MAAM,cAAc,GAAG,IAAI;AAE3B,QAAA,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,EAAE;QAEzC,IACE,MAAM,KAAK,SAAS;;aAEnB,qBAAqB,CAAC,MAAM,CAAC;;AAE5B,gBAAA,4BAA4B,CAAC,MAAM,CAAC,CAAC,EACvC;AACA,YAAA,cAAc,CAAC,eAAe,CAAC,oBAAoB,CAAC;YAEpD;QACF;AAEA,QAAA,cAAc,CAAC,eAAe,CAAC,SAAS,CAAC;QAEzC;IACF;IAEA,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE;QACtC,aAAa,CAAC,KAAK,CAAC;IACtB;AACF,CAAC;;;;"}
|
package/dist/functions/index.mjs
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
export { appendAsConstTransformer } from './ast-transformers/append-as-const.mjs';
|
|
1
2
|
export { convertInterfaceToTypeTransformer } from './ast-transformers/convert-interface-to-type.mjs';
|
|
2
3
|
export { convertToReadonlyTypeTransformer } from './ast-transformers/convert-to-readonly-type.mjs';
|
|
3
4
|
export { compareUnionIntersectionTypes } from './ast-transformers/readonly-transformer-helpers/compare-union-types.mjs';
|
|
4
5
|
export { invalidDeepReadonlyTypeName } from './ast-transformers/readonly-transformer-helpers/constants.mjs';
|
|
5
6
|
export { groupUnionIntersectionTypes } from './ast-transformers/readonly-transformer-helpers/group-union-types.mjs';
|
|
6
7
|
export { nextReadonlyContext } from './ast-transformers/readonly-transformer-helpers/readonly-context.mjs';
|
|
8
|
+
export { replaceAnyWithUnknownTransformer } from './ast-transformers/replace-any-with-unknown.mjs';
|
|
7
9
|
export { replaceRecordWithUnknownRecordTransformer } from './ast-transformers/replace-record-with-unknown-record.mjs';
|
|
8
10
|
export { transformSourceCode } from './ast-transformers/transform-source-code.mjs';
|
|
9
11
|
export { IGNORE_FILE_COMMENT_TEXT, IGNORE_LINE_COMMENT_TEXT } from './constants/ignore-comment-text.mjs';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
export { appendAsConstTransformer } from './functions/ast-transformers/append-as-const.mjs';
|
|
1
2
|
export { convertInterfaceToTypeTransformer } from './functions/ast-transformers/convert-interface-to-type.mjs';
|
|
2
3
|
export { convertToReadonlyTypeTransformer } from './functions/ast-transformers/convert-to-readonly-type.mjs';
|
|
3
4
|
export { compareUnionIntersectionTypes } from './functions/ast-transformers/readonly-transformer-helpers/compare-union-types.mjs';
|
|
4
5
|
export { invalidDeepReadonlyTypeName } from './functions/ast-transformers/readonly-transformer-helpers/constants.mjs';
|
|
5
6
|
export { groupUnionIntersectionTypes } from './functions/ast-transformers/readonly-transformer-helpers/group-union-types.mjs';
|
|
6
7
|
export { nextReadonlyContext } from './functions/ast-transformers/readonly-transformer-helpers/readonly-context.mjs';
|
|
8
|
+
export { replaceAnyWithUnknownTransformer } from './functions/ast-transformers/replace-any-with-unknown.mjs';
|
|
7
9
|
export { replaceRecordWithUnknownRecordTransformer } from './functions/ast-transformers/replace-record-with-unknown-record.mjs';
|
|
8
10
|
export { transformSourceCode } from './functions/ast-transformers/transform-source-code.mjs';
|
|
9
11
|
export { IGNORE_FILE_COMMENT_TEXT, IGNORE_LINE_COMMENT_TEXT } from './functions/constants/ignore-comment-text.mjs';
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-codemod-lib",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -27,8 +27,10 @@
|
|
|
27
27
|
"module": "./dist/entry-point.mjs",
|
|
28
28
|
"types": "./dist/types.d.mts",
|
|
29
29
|
"bin": {
|
|
30
|
+
"append-as-const": "./dist/cmd/append-as-const.mjs",
|
|
30
31
|
"convert-interface-to-type": "./dist/cmd/convert-interface-to-type.mjs",
|
|
31
32
|
"convert-to-readonly": "./dist/cmd/convert-to-readonly.mjs",
|
|
33
|
+
"replace-any-with-unknown": "./dist/cmd/replace-any-with-unknown.mjs",
|
|
32
34
|
"replace-record-with-unknown-record": "./dist/cmd/replace-record-with-unknown-record.mjs"
|
|
33
35
|
},
|
|
34
36
|
"files": [
|
|
@@ -37,59 +39,6 @@
|
|
|
37
39
|
"README.md",
|
|
38
40
|
"LICENSE"
|
|
39
41
|
],
|
|
40
|
-
"dependencies": {
|
|
41
|
-
"cmd-ts": "0.14.3",
|
|
42
|
-
"dedent": "1.7.1",
|
|
43
|
-
"ts-morph": "27.0.2",
|
|
44
|
-
"ts-repo-utils": "8.0.2"
|
|
45
|
-
},
|
|
46
|
-
"devDependencies": {
|
|
47
|
-
"@rollup/plugin-replace": "6.0.3",
|
|
48
|
-
"@rollup/plugin-strip": "3.0.4",
|
|
49
|
-
"@rollup/plugin-typescript": "12.3.0",
|
|
50
|
-
"@semantic-release/changelog": "6.0.3",
|
|
51
|
-
"@semantic-release/commit-analyzer": "13.0.1",
|
|
52
|
-
"@semantic-release/exec": "7.1.0",
|
|
53
|
-
"@semantic-release/git": "10.0.1",
|
|
54
|
-
"@semantic-release/github": "12.0.2",
|
|
55
|
-
"@semantic-release/npm": "13.1.3",
|
|
56
|
-
"@semantic-release/release-notes-generator": "14.1.0",
|
|
57
|
-
"@types/node": "25.0.6",
|
|
58
|
-
"@vitest/browser-playwright": "4.0.16",
|
|
59
|
-
"@vitest/coverage-v8": "4.0.16",
|
|
60
|
-
"@vitest/ui": "4.0.16",
|
|
61
|
-
"conventional-changelog-conventionalcommits": "9.1.0",
|
|
62
|
-
"cspell": "9.4.0",
|
|
63
|
-
"eslint": "9.39.2",
|
|
64
|
-
"eslint-config-typed": "4.4.1",
|
|
65
|
-
"github-settings-as-code": "1.0.7",
|
|
66
|
-
"jiti": "2.6.1",
|
|
67
|
-
"markdownlint": "0.40.0",
|
|
68
|
-
"markdownlint-cli2": "0.20.0",
|
|
69
|
-
"npm-run-all2": "8.0.4",
|
|
70
|
-
"playwright": "1.57.0",
|
|
71
|
-
"prettier": "3.7.4",
|
|
72
|
-
"prettier-plugin-organize-imports": "4.3.0",
|
|
73
|
-
"prettier-plugin-packagejson": "2.5.20",
|
|
74
|
-
"rollup": "4.54.0",
|
|
75
|
-
"semantic-release": "25.0.2",
|
|
76
|
-
"ts-data-forge": "6.2.1",
|
|
77
|
-
"ts-type-forge": "2.3.0",
|
|
78
|
-
"tslib": "2.8.1",
|
|
79
|
-
"tsx": "4.21.0",
|
|
80
|
-
"typedoc": "0.28.15",
|
|
81
|
-
"typedoc-github-theme": "0.3.1",
|
|
82
|
-
"typescript": "5.9.3",
|
|
83
|
-
"vite": "7.3.0",
|
|
84
|
-
"vitest": "4.0.16"
|
|
85
|
-
},
|
|
86
|
-
"engines": {
|
|
87
|
-
"node": ">=22",
|
|
88
|
-
"pnpm": ">=8.0.0"
|
|
89
|
-
},
|
|
90
|
-
"volta": {
|
|
91
|
-
"node": "25.2.1"
|
|
92
|
-
},
|
|
93
42
|
"scripts": {
|
|
94
43
|
"build": "tsx ./scripts/cmd/build.mts",
|
|
95
44
|
"build:min": "tsx ./scripts/cmd/build.mts --skip-check",
|
|
@@ -117,7 +66,8 @@
|
|
|
117
66
|
"lint": "eslint .",
|
|
118
67
|
"lint:fix": "eslint . --fix",
|
|
119
68
|
"md": "markdownlint-cli2",
|
|
120
|
-
"run:cmd": "tsx ./src/cmd/convert-to-readonly.mts ./test/
|
|
69
|
+
"run:cmd": "tsx ./src/cmd/convert-to-readonly.mts ./test/sample1.mts",
|
|
70
|
+
"run:test": "tsx ./scripts/test-code/transform-test-code.mts",
|
|
121
71
|
"test": "pnpm run z:vitest:node run",
|
|
122
72
|
"test:browser": "pnpm run z:vitest --project='Browser' run",
|
|
123
73
|
"test:cov": "pnpm run z:vitest:node run --coverage",
|
|
@@ -129,6 +79,60 @@
|
|
|
129
79
|
"type-check": "tsc --noEmit",
|
|
130
80
|
"update-packages": "pnpm update --latest",
|
|
131
81
|
"z:vitest": "vitest --config ./configs/vitest.config.mts",
|
|
132
|
-
"z:vitest:node": "
|
|
82
|
+
"z:vitest:node": "pnpm run z:vitest --project='Node.js'"
|
|
83
|
+
},
|
|
84
|
+
"dependencies": {
|
|
85
|
+
"cmd-ts": "0.14.3",
|
|
86
|
+
"dedent": "1.7.1",
|
|
87
|
+
"ts-morph": "27.0.2",
|
|
88
|
+
"ts-repo-utils": "8.0.2"
|
|
89
|
+
},
|
|
90
|
+
"devDependencies": {
|
|
91
|
+
"@rollup/plugin-replace": "6.0.3",
|
|
92
|
+
"@rollup/plugin-strip": "3.0.4",
|
|
93
|
+
"@rollup/plugin-typescript": "12.3.0",
|
|
94
|
+
"@semantic-release/changelog": "6.0.3",
|
|
95
|
+
"@semantic-release/commit-analyzer": "13.0.1",
|
|
96
|
+
"@semantic-release/exec": "7.1.0",
|
|
97
|
+
"@semantic-release/git": "10.0.1",
|
|
98
|
+
"@semantic-release/github": "12.0.2",
|
|
99
|
+
"@semantic-release/npm": "13.1.3",
|
|
100
|
+
"@semantic-release/release-notes-generator": "14.1.0",
|
|
101
|
+
"@types/node": "25.0.9",
|
|
102
|
+
"@vitest/browser-playwright": "4.0.17",
|
|
103
|
+
"@vitest/coverage-v8": "4.0.17",
|
|
104
|
+
"@vitest/ui": "4.0.17",
|
|
105
|
+
"conventional-changelog-conventionalcommits": "9.1.0",
|
|
106
|
+
"cspell": "9.6.0",
|
|
107
|
+
"eslint": "9.39.2",
|
|
108
|
+
"eslint-config-typed": "4.5.0",
|
|
109
|
+
"github-settings-as-code": "1.0.11",
|
|
110
|
+
"jiti": "2.6.1",
|
|
111
|
+
"markdownlint": "0.40.0",
|
|
112
|
+
"markdownlint-cli2": "0.20.0",
|
|
113
|
+
"npm-run-all2": "8.0.4",
|
|
114
|
+
"playwright": "1.57.0",
|
|
115
|
+
"prettier": "3.8.0",
|
|
116
|
+
"prettier-plugin-organize-imports": "4.3.0",
|
|
117
|
+
"prettier-plugin-packagejson": "2.5.21",
|
|
118
|
+
"rollup": "4.55.1",
|
|
119
|
+
"semantic-release": "25.0.2",
|
|
120
|
+
"ts-data-forge": "6.2.1",
|
|
121
|
+
"ts-type-forge": "2.3.0",
|
|
122
|
+
"tslib": "2.8.1",
|
|
123
|
+
"tsx": "4.21.0",
|
|
124
|
+
"typedoc": "0.28.16",
|
|
125
|
+
"typedoc-github-theme": "0.3.1",
|
|
126
|
+
"typescript": "5.9.3",
|
|
127
|
+
"vite": "7.3.1",
|
|
128
|
+
"vitest": "4.0.17"
|
|
129
|
+
},
|
|
130
|
+
"packageManager": "pnpm@10.27.0",
|
|
131
|
+
"engines": {
|
|
132
|
+
"node": ">=20.11.0",
|
|
133
|
+
"pnpm": ">=8.0.0"
|
|
134
|
+
},
|
|
135
|
+
"volta": {
|
|
136
|
+
"node": "25.2.1"
|
|
133
137
|
}
|
|
134
|
-
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* eslint-disable no-await-in-loop */
|
|
3
|
+
|
|
4
|
+
import * as cmd from 'cmd-ts';
|
|
5
|
+
import dedent from 'dedent';
|
|
6
|
+
import { castMutable, Result, unknownToString } from 'ts-data-forge';
|
|
7
|
+
import 'ts-repo-utils';
|
|
8
|
+
import {
|
|
9
|
+
appendAsConstTransformer,
|
|
10
|
+
transformSourceCode,
|
|
11
|
+
} from '../functions/index.mjs';
|
|
12
|
+
|
|
13
|
+
const cmdDef = cmd.command({
|
|
14
|
+
name: 'append-as-const-cli',
|
|
15
|
+
version: '1.0.0',
|
|
16
|
+
args: {
|
|
17
|
+
baseDir: cmd.positional({
|
|
18
|
+
type: cmd.string,
|
|
19
|
+
displayName: 'baseDir',
|
|
20
|
+
description: 'The base directory in which to perform the conversion',
|
|
21
|
+
}),
|
|
22
|
+
exclude: cmd.multioption({
|
|
23
|
+
long: 'exclude',
|
|
24
|
+
type: cmd.optional(cmd.array(cmd.string)),
|
|
25
|
+
description:
|
|
26
|
+
'Glob patterns of files to exclude from the base directory (e.g., "src/generated/**/*.mts")',
|
|
27
|
+
}),
|
|
28
|
+
silent: cmd.flag({
|
|
29
|
+
long: 'silent',
|
|
30
|
+
type: cmd.optional(cmd.boolean),
|
|
31
|
+
description: 'If true, suppresses output messages (default: false)',
|
|
32
|
+
}),
|
|
33
|
+
},
|
|
34
|
+
handler: (args) => {
|
|
35
|
+
appendAsConstCLI({
|
|
36
|
+
baseDir: args.baseDir,
|
|
37
|
+
exclude: args.exclude ?? [],
|
|
38
|
+
silent: args.silent ?? false,
|
|
39
|
+
}).catch((error: unknown) => {
|
|
40
|
+
console.error('An error occurred:', error);
|
|
41
|
+
|
|
42
|
+
process.exit(1);
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
type Args = Readonly<{
|
|
48
|
+
baseDir: string;
|
|
49
|
+
exclude: readonly string[];
|
|
50
|
+
silent: boolean;
|
|
51
|
+
}>;
|
|
52
|
+
|
|
53
|
+
const appendAsConstCLI = async (
|
|
54
|
+
args: Args,
|
|
55
|
+
): Promise<Result<undefined, undefined>> => {
|
|
56
|
+
const echoIfNotSilent = args.silent ? () => {} : echo;
|
|
57
|
+
|
|
58
|
+
const errorIfNotSilent = args.silent ? () => {} : console.error;
|
|
59
|
+
|
|
60
|
+
// Find all files matching the glob
|
|
61
|
+
const globResult = await glob(args.baseDir, {
|
|
62
|
+
ignore: castMutable(args.exclude),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
if (Result.isErr(globResult)) {
|
|
66
|
+
errorIfNotSilent('Error finding files matching pattern:', globResult.value);
|
|
67
|
+
|
|
68
|
+
return Result.err(undefined);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const files = globResult.value;
|
|
72
|
+
|
|
73
|
+
if (files.length === 0) {
|
|
74
|
+
echoIfNotSilent('No files found matching pattern:', args.baseDir);
|
|
75
|
+
|
|
76
|
+
return Result.ok(undefined);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const { errorFiles, transformedCount, unchangedCount } = await transformFiles(
|
|
80
|
+
files,
|
|
81
|
+
args.silent,
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const hr = '='.repeat(50);
|
|
85
|
+
|
|
86
|
+
echoIfNotSilent(dedent`
|
|
87
|
+
${hr}
|
|
88
|
+
Summary:
|
|
89
|
+
✅ Transformed: ${transformedCount}
|
|
90
|
+
⏭️ Unchanged: ${unchangedCount}
|
|
91
|
+
❌ Errors: ${errorFiles.length}
|
|
92
|
+
📊 Total: ${files.length}
|
|
93
|
+
`);
|
|
94
|
+
|
|
95
|
+
if (errorFiles.length > 0) {
|
|
96
|
+
echoIfNotSilent('\nFiles with errors:');
|
|
97
|
+
|
|
98
|
+
for (const fileName of errorFiles) {
|
|
99
|
+
echoIfNotSilent(` - ${fileName}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
echoIfNotSilent(hr);
|
|
104
|
+
|
|
105
|
+
if (errorFiles.length > 0) {
|
|
106
|
+
return Result.err(undefined);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return Result.ok(undefined);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const transformFiles = async (
|
|
113
|
+
filePaths: readonly string[],
|
|
114
|
+
silent: boolean,
|
|
115
|
+
): Promise<
|
|
116
|
+
Readonly<{
|
|
117
|
+
transformedCount: number;
|
|
118
|
+
unchangedCount: number;
|
|
119
|
+
errorFiles: readonly string[];
|
|
120
|
+
}>
|
|
121
|
+
> => {
|
|
122
|
+
let mut_transformedCount: number = 0;
|
|
123
|
+
|
|
124
|
+
let mut_unchangedCount: number = 0;
|
|
125
|
+
|
|
126
|
+
const mut_errorFiles: string[] = [];
|
|
127
|
+
|
|
128
|
+
for (const filePath of filePaths) {
|
|
129
|
+
const result = await transformOneFile(filePath, silent);
|
|
130
|
+
|
|
131
|
+
if (Result.isOk(result)) {
|
|
132
|
+
switch (result.value) {
|
|
133
|
+
case 'transformed':
|
|
134
|
+
mut_transformedCount += 1;
|
|
135
|
+
|
|
136
|
+
break;
|
|
137
|
+
|
|
138
|
+
case 'unchanged':
|
|
139
|
+
mut_unchangedCount += 1;
|
|
140
|
+
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
mut_errorFiles.push(path.basename(filePath));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
transformedCount: mut_transformedCount,
|
|
150
|
+
unchangedCount: mut_unchangedCount,
|
|
151
|
+
errorFiles: mut_errorFiles,
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const transformOneFile = async (
|
|
156
|
+
filePath: string,
|
|
157
|
+
silent: boolean,
|
|
158
|
+
): Promise<Result<'unchanged' | 'transformed', string>> => {
|
|
159
|
+
const echoIfNotSilent = silent ? () => {} : echo;
|
|
160
|
+
|
|
161
|
+
const errorIfNotSilent = silent ? () => {} : console.error;
|
|
162
|
+
|
|
163
|
+
const fileName = path.basename(filePath);
|
|
164
|
+
|
|
165
|
+
const isTsx = fileName.endsWith('.tsx') || fileName.endsWith('.jsx');
|
|
166
|
+
|
|
167
|
+
try {
|
|
168
|
+
const originalCode = await fs.readFile(filePath, 'utf8');
|
|
169
|
+
|
|
170
|
+
// Transform the code with all transformers
|
|
171
|
+
const transformedCode = transformSourceCode(originalCode, isTsx, [
|
|
172
|
+
appendAsConstTransformer(),
|
|
173
|
+
]);
|
|
174
|
+
|
|
175
|
+
// Check if the code was actually changed
|
|
176
|
+
if (transformedCode === originalCode) {
|
|
177
|
+
echoIfNotSilent(`⏭️ ${fileName} - no changes needed`);
|
|
178
|
+
|
|
179
|
+
return Result.ok('unchanged');
|
|
180
|
+
} else {
|
|
181
|
+
// Write back the transformed code
|
|
182
|
+
await fs.writeFile(filePath, transformedCode, 'utf8');
|
|
183
|
+
|
|
184
|
+
echoIfNotSilent(`✅ ${fileName} - transformed`);
|
|
185
|
+
|
|
186
|
+
return Result.ok('transformed');
|
|
187
|
+
}
|
|
188
|
+
} catch (error) {
|
|
189
|
+
const errStr = unknownToString(error);
|
|
190
|
+
|
|
191
|
+
errorIfNotSilent(`❌ ${fileName} - error: ${errStr}`);
|
|
192
|
+
|
|
193
|
+
return Result.err(errStr);
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
await cmd.run(cmdDef, process.argv.slice(2));
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* eslint-disable no-await-in-loop */
|
|
3
|
+
|
|
4
|
+
import * as cmd from 'cmd-ts';
|
|
5
|
+
import dedent from 'dedent';
|
|
6
|
+
import { castMutable, Result, unknownToString } from 'ts-data-forge';
|
|
7
|
+
import 'ts-repo-utils';
|
|
8
|
+
import {
|
|
9
|
+
convertInterfaceToTypeTransformer,
|
|
10
|
+
transformSourceCode,
|
|
11
|
+
} from '../functions/index.mjs';
|
|
12
|
+
|
|
13
|
+
const cmdDef = cmd.command({
|
|
14
|
+
name: 'convert-interface-to-type-cli',
|
|
15
|
+
version: '1.0.0',
|
|
16
|
+
args: {
|
|
17
|
+
baseDir: cmd.positional({
|
|
18
|
+
type: cmd.string,
|
|
19
|
+
displayName: 'baseDir',
|
|
20
|
+
description: 'The base directory in which to perform the conversion',
|
|
21
|
+
}),
|
|
22
|
+
exclude: cmd.multioption({
|
|
23
|
+
long: 'exclude',
|
|
24
|
+
type: cmd.optional(cmd.array(cmd.string)),
|
|
25
|
+
description:
|
|
26
|
+
'Glob patterns of files to exclude from the base directory (e.g., "src/generated/**/*.mts")',
|
|
27
|
+
}),
|
|
28
|
+
silent: cmd.flag({
|
|
29
|
+
long: 'silent',
|
|
30
|
+
type: cmd.optional(cmd.boolean),
|
|
31
|
+
description: 'If true, suppresses output messages (default: false)',
|
|
32
|
+
}),
|
|
33
|
+
},
|
|
34
|
+
handler: (args) => {
|
|
35
|
+
convertInterfaceToTypeCLI({
|
|
36
|
+
baseDir: args.baseDir,
|
|
37
|
+
exclude: args.exclude ?? [],
|
|
38
|
+
silent: args.silent ?? false,
|
|
39
|
+
}).catch((error: unknown) => {
|
|
40
|
+
console.error('An error occurred:', error);
|
|
41
|
+
|
|
42
|
+
process.exit(1);
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
type Args = Readonly<{
|
|
48
|
+
baseDir: string;
|
|
49
|
+
exclude: readonly string[];
|
|
50
|
+
silent: boolean;
|
|
51
|
+
}>;
|
|
52
|
+
|
|
53
|
+
const convertInterfaceToTypeCLI = async (
|
|
54
|
+
args: Args,
|
|
55
|
+
): Promise<Result<undefined, undefined>> => {
|
|
56
|
+
const echoIfNotSilent = args.silent ? () => {} : echo;
|
|
57
|
+
|
|
58
|
+
const errorIfNotSilent = args.silent ? () => {} : console.error;
|
|
59
|
+
|
|
60
|
+
// Find all files matching the glob
|
|
61
|
+
const globResult = await glob(args.baseDir, {
|
|
62
|
+
ignore: castMutable(args.exclude),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
if (Result.isErr(globResult)) {
|
|
66
|
+
errorIfNotSilent('Error finding files matching pattern:', globResult.value);
|
|
67
|
+
|
|
68
|
+
return Result.err(undefined);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const files = globResult.value;
|
|
72
|
+
|
|
73
|
+
if (files.length === 0) {
|
|
74
|
+
echoIfNotSilent('No files found matching pattern:', args.baseDir);
|
|
75
|
+
|
|
76
|
+
return Result.ok(undefined);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const { errorFiles, transformedCount, unchangedCount } = await transformFiles(
|
|
80
|
+
files,
|
|
81
|
+
args.silent,
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const hr = '='.repeat(50);
|
|
85
|
+
|
|
86
|
+
echoIfNotSilent(dedent`
|
|
87
|
+
${hr}
|
|
88
|
+
Summary:
|
|
89
|
+
✅ Transformed: ${transformedCount}
|
|
90
|
+
⏭️ Unchanged: ${unchangedCount}
|
|
91
|
+
❌ Errors: ${errorFiles.length}
|
|
92
|
+
📊 Total: ${files.length}
|
|
93
|
+
`);
|
|
94
|
+
|
|
95
|
+
if (errorFiles.length > 0) {
|
|
96
|
+
echoIfNotSilent('\nFiles with errors:');
|
|
97
|
+
|
|
98
|
+
for (const fileName of errorFiles) {
|
|
99
|
+
echoIfNotSilent(` - ${fileName}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
echoIfNotSilent(hr);
|
|
104
|
+
|
|
105
|
+
if (errorFiles.length > 0) {
|
|
106
|
+
return Result.err(undefined);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return Result.ok(undefined);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const transformFiles = async (
|
|
113
|
+
filePaths: readonly string[],
|
|
114
|
+
silent: boolean,
|
|
115
|
+
): Promise<
|
|
116
|
+
Readonly<{
|
|
117
|
+
transformedCount: number;
|
|
118
|
+
unchangedCount: number;
|
|
119
|
+
errorFiles: readonly string[];
|
|
120
|
+
}>
|
|
121
|
+
> => {
|
|
122
|
+
let mut_transformedCount: number = 0;
|
|
123
|
+
|
|
124
|
+
let mut_unchangedCount: number = 0;
|
|
125
|
+
|
|
126
|
+
const mut_errorFiles: string[] = [];
|
|
127
|
+
|
|
128
|
+
for (const filePath of filePaths) {
|
|
129
|
+
const result = await transformOneFile(filePath, silent);
|
|
130
|
+
|
|
131
|
+
if (Result.isOk(result)) {
|
|
132
|
+
switch (result.value) {
|
|
133
|
+
case 'transformed':
|
|
134
|
+
mut_transformedCount += 1;
|
|
135
|
+
|
|
136
|
+
break;
|
|
137
|
+
|
|
138
|
+
case 'unchanged':
|
|
139
|
+
mut_unchangedCount += 1;
|
|
140
|
+
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
mut_errorFiles.push(path.basename(filePath));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
transformedCount: mut_transformedCount,
|
|
150
|
+
unchangedCount: mut_unchangedCount,
|
|
151
|
+
errorFiles: mut_errorFiles,
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const transformOneFile = async (
|
|
156
|
+
filePath: string,
|
|
157
|
+
silent: boolean,
|
|
158
|
+
): Promise<Result<'unchanged' | 'transformed', string>> => {
|
|
159
|
+
const echoIfNotSilent = silent ? () => {} : echo;
|
|
160
|
+
|
|
161
|
+
const errorIfNotSilent = silent ? () => {} : console.error;
|
|
162
|
+
|
|
163
|
+
const fileName = path.basename(filePath);
|
|
164
|
+
|
|
165
|
+
const isTsx = fileName.endsWith('.tsx') || fileName.endsWith('.jsx');
|
|
166
|
+
|
|
167
|
+
try {
|
|
168
|
+
const originalCode = await fs.readFile(filePath, 'utf8');
|
|
169
|
+
|
|
170
|
+
// Transform the code with all transformers
|
|
171
|
+
const transformedCode = transformSourceCode(originalCode, isTsx, [
|
|
172
|
+
convertInterfaceToTypeTransformer(),
|
|
173
|
+
]);
|
|
174
|
+
|
|
175
|
+
// Check if the code was actually changed
|
|
176
|
+
if (transformedCode === originalCode) {
|
|
177
|
+
echoIfNotSilent(`⏭️ ${fileName} - no changes needed`);
|
|
178
|
+
|
|
179
|
+
return Result.ok('unchanged');
|
|
180
|
+
} else {
|
|
181
|
+
// Write back the transformed code
|
|
182
|
+
await fs.writeFile(filePath, transformedCode, 'utf8');
|
|
183
|
+
|
|
184
|
+
echoIfNotSilent(`✅ ${fileName} - transformed`);
|
|
185
|
+
|
|
186
|
+
return Result.ok('transformed');
|
|
187
|
+
}
|
|
188
|
+
} catch (error) {
|
|
189
|
+
const errStr = unknownToString(error);
|
|
190
|
+
|
|
191
|
+
errorIfNotSilent(`❌ ${fileName} - error: ${errStr}`);
|
|
192
|
+
|
|
193
|
+
return Result.err(errStr);
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
await cmd.run(cmdDef, process.argv.slice(2));
|
|
@@ -162,11 +162,13 @@ const transformOneFile = async (
|
|
|
162
162
|
|
|
163
163
|
const fileName = path.basename(filePath);
|
|
164
164
|
|
|
165
|
+
const isTsx = fileName.endsWith('.tsx') || fileName.endsWith('.jsx');
|
|
166
|
+
|
|
165
167
|
try {
|
|
166
168
|
const originalCode = await fs.readFile(filePath, 'utf8');
|
|
167
169
|
|
|
168
170
|
// Transform the code with all transformers
|
|
169
|
-
const transformedCode = transformSourceCode(originalCode,
|
|
171
|
+
const transformedCode = transformSourceCode(originalCode, isTsx, [
|
|
170
172
|
convertToReadonlyTypeTransformer(),
|
|
171
173
|
]);
|
|
172
174
|
|