ts-codemod-lib 2.2.4 → 3.0.0
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 +15 -54
- package/dist/functions/ast-transformers/convert-to-readonly.d.mts.map +1 -1
- package/dist/functions/ast-transformers/convert-to-readonly.mjs +2 -3
- package/dist/functions/ast-transformers/convert-to-readonly.mjs.map +1 -1
- package/dist/functions/ast-transformers/readonly-transformer-helpers/readonly-context.d.mts +3 -3
- package/dist/functions/ast-transformers/readonly-transformer-helpers/readonly-context.d.mts.map +1 -1
- package/dist/functions/ast-transformers/readonly-transformer-helpers/readonly-context.mjs.map +1 -1
- package/dist/functions/ast-transformers/transform-source-code.mjs +1 -1
- package/dist/functions/ast-transformers/transform-source-code.mjs.map +1 -1
- package/dist/functions/functions/is-readonly-node.d.mts +5 -5
- package/dist/functions/functions/is-readonly-node.d.mts.map +1 -1
- package/dist/functions/functions/is-readonly-node.mjs.map +1 -1
- package/dist/functions/functions/should-avoid-parentheses-for-readonly.d.mts.map +1 -1
- package/dist/functions/functions/should-avoid-parentheses-for-readonly.mjs +1 -4
- package/dist/functions/functions/should-avoid-parentheses-for-readonly.mjs.map +1 -1
- package/package.json +69 -115
- package/src/functions/ast-transformers/convert-to-readonly.mts +20 -17
- package/src/functions/ast-transformers/readonly-transformer-helpers/readonly-context.mts +3 -3
- package/src/functions/ast-transformers/transform-source-code.mts +1 -1
- package/src/functions/functions/is-readonly-node.mts +5 -5
- package/src/functions/functions/should-avoid-parentheses-for-readonly.mts +1 -5
- package/dist/cmd/append-as-const.d.mts +0 -3
- package/dist/cmd/append-as-const.d.mts.map +0 -1
- package/dist/cmd/append-as-const.mjs +0 -63
- package/dist/cmd/append-as-const.mjs.map +0 -1
- package/dist/cmd/convert-interface-to-type.d.mts +0 -3
- package/dist/cmd/convert-interface-to-type.d.mts.map +0 -1
- package/dist/cmd/convert-interface-to-type.mjs +0 -63
- package/dist/cmd/convert-interface-to-type.mjs.map +0 -1
- package/dist/cmd/convert-to-readonly.d.mts +0 -3
- package/dist/cmd/convert-to-readonly.d.mts.map +0 -1
- package/dist/cmd/convert-to-readonly.mjs +0 -63
- package/dist/cmd/convert-to-readonly.mjs.map +0 -1
- package/dist/cmd/replace-any-with-unknown.d.mts +0 -3
- package/dist/cmd/replace-any-with-unknown.d.mts.map +0 -1
- package/dist/cmd/replace-any-with-unknown.mjs +0 -63
- package/dist/cmd/replace-any-with-unknown.mjs.map +0 -1
- package/dist/cmd/replace-record-with-unknown-record.d.mts +0 -3
- package/dist/cmd/replace-record-with-unknown-record.d.mts.map +0 -1
- package/dist/cmd/replace-record-with-unknown-record.mjs +0 -63
- package/dist/cmd/replace-record-with-unknown-record.mjs.map +0 -1
- package/dist/cmd/run-transformer-cli.d.mts +0 -13
- package/dist/cmd/run-transformer-cli.d.mts.map +0 -1
- package/dist/cmd/run-transformer-cli.mjs +0 -176
- package/dist/cmd/run-transformer-cli.mjs.map +0 -1
- package/src/cmd/append-as-const.mts +0 -67
- package/src/cmd/convert-interface-to-type.mts +0 -67
- package/src/cmd/convert-to-readonly.mts +0 -67
- package/src/cmd/replace-any-with-unknown.mts +0 -67
- package/src/cmd/replace-record-with-unknown-record.mts +0 -67
- package/src/cmd/run-transformer-cli.mts +0 -307
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import * as tsm from 'ts-morph';
|
|
2
|
-
import { type DeepReadonly } from 'ts-type-forge';
|
|
2
|
+
import { type DeepReadonly, type StrictOmit } from 'ts-type-forge';
|
|
3
3
|
export declare const isShallowReadonlyTypeNode: (node: tsm.Node) => boolean;
|
|
4
4
|
export declare const isReadonlyTupleOrArrayTypeNode: (node: DeepReadonly<tsm.Node>) => node is ReadonlyArrayTypeNode | ReadonlyTupleTypeNode;
|
|
5
|
-
export type ReadonlyArrayTypeNode = tsm.TypeNode &
|
|
5
|
+
export type ReadonlyArrayTypeNode = tsm.TypeNode & StrictOmit<tsm.TypeOperatorTypeNode, 'getOperator' | 'getTypeNode'> & Readonly<{
|
|
6
6
|
getOperator: () => tsm.SyntaxKind.ReadonlyKeyword;
|
|
7
7
|
getTypeNode: () => tsm.ArrayTypeNode;
|
|
8
8
|
}>;
|
|
9
9
|
export declare const isReadonlyArrayTypeNode: (node: DeepReadonly<tsm.Node>) => node is ReadonlyArrayTypeNode;
|
|
10
|
-
export type ReadonlyTupleTypeNode = tsm.TypeNode &
|
|
10
|
+
export type ReadonlyTupleTypeNode = tsm.TypeNode & StrictOmit<tsm.TypeOperatorTypeNode, 'getOperator' | 'getTypeNode'> & Readonly<{
|
|
11
11
|
getOperator: () => tsm.SyntaxKind.ReadonlyKeyword;
|
|
12
12
|
getTypeNode: () => tsm.TupleTypeNode;
|
|
13
13
|
}>;
|
|
14
14
|
export declare const isReadonlyTupleTypeNode: (node: DeepReadonly<tsm.Node>) => node is ReadonlyTupleTypeNode;
|
|
15
|
-
export type ReadonlyTypeReferenceNode = tsm.TypeNode &
|
|
16
|
-
getTypeName: () =>
|
|
15
|
+
export type ReadonlyTypeReferenceNode = tsm.TypeNode & StrictOmit<tsm.TypeReferenceNode, 'getTypeName' | 'getTypeArguments'> & Readonly<{
|
|
16
|
+
getTypeName: () => StrictOmit<tsm.Identifier, 'getText'> & Readonly<{
|
|
17
17
|
getText: () => 'Readonly';
|
|
18
18
|
}>;
|
|
19
19
|
getTypeArguments: () => readonly [tsm.TypeNode];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"is-readonly-node.d.mts","sourceRoot":"","sources":["../../../src/functions/functions/is-readonly-node.mts"],"names":[],"mappings":"AACA,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"is-readonly-node.d.mts","sourceRoot":"","sources":["../../../src/functions/functions/is-readonly-node.mts"],"names":[],"mappings":"AACA,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAGnE,eAAO,MAAM,yBAAyB,SAAU,GAAG,CAAC,IAAI,KAAG,OAGnC,CAAC;AAEzB,eAAO,MAAM,8BAA8B,SACnC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,KAC3B,IAAI,IAAI,qBAAqB,GAAG,qBAIqB,CAAC;AAEzD,MAAM,MAAM,qBAAqB,GAAG,GAAG,CAAC,QAAQ,GAC9C,UAAU,CAAC,GAAG,CAAC,oBAAoB,EAAE,aAAa,GAAG,aAAa,CAAC,GACnE,QAAQ,CAAC;IACP,WAAW,EAAE,MAAM,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC;IAClD,WAAW,EAAE,MAAM,GAAG,CAAC,aAAa,CAAC;CACtC,CAAC,CAAC;AAEL,eAAO,MAAM,uBAAuB,SAC5B,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,KAC3B,IAAI,IAAI,qBAG0C,CAAC;AA8DtD,MAAM,MAAM,qBAAqB,GAAG,GAAG,CAAC,QAAQ,GAC9C,UAAU,CAAC,GAAG,CAAC,oBAAoB,EAAE,aAAa,GAAG,aAAa,CAAC,GACnE,QAAQ,CAAC;IACP,WAAW,EAAE,MAAM,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC;IAClD,WAAW,EAAE,MAAM,GAAG,CAAC,aAAa,CAAC;CACtC,CAAC,CAAC;AAEL,eAAO,MAAM,uBAAuB,SAC5B,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,KAC3B,IAAI,IAAI,qBAG0C,CAAC;AAkDtD,MAAM,MAAM,yBAAyB,GAAG,GAAG,CAAC,QAAQ,GAClD,UAAU,CAAC,GAAG,CAAC,iBAAiB,EAAE,aAAa,GAAG,kBAAkB,CAAC,GACrE,QAAQ,CAAC;IACP,WAAW,EAAE,MAAM,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,SAAS,CAAC,GACtD,QAAQ,CAAC;QACP,OAAO,EAAE,MAAM,UAAU,CAAC;KAC3B,CAAC,CAAC;IACL,gBAAgB,EAAE,MAAM,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;CACjD,CAAC,CAAC;AAEL,eAAO,MAAM,2BAA2B,SAChC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,KAC3B,IAAI,IAAI,yBAcV,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"is-readonly-node.mjs","sources":["../../../src/functions/functions/is-readonly-node.mts"],"sourcesContent":["import { Arr, expectType } from 'ts-data-forge';\nimport * as tsm from 'ts-morph';\nimport { type DeepReadonly } from 'ts-type-forge';\nimport { isAtomicTypeNode } from './is-atomic-type-node.mjs';\n\nexport const isShallowReadonlyTypeNode = (node: tsm.Node): boolean =>\n isReadonlyTupleOrArrayTypeNode(node) ||\n isReadonlyTypeReferenceNode(node) ||\n isAtomicTypeNode(node);\n\nexport const isReadonlyTupleOrArrayTypeNode = (\n node: DeepReadonly<tsm.Node>,\n): node is ReadonlyArrayTypeNode | ReadonlyTupleTypeNode =>\n node.isKind(tsm.SyntaxKind.TypeOperator) &&\n node.getOperator() === tsm.SyntaxKind.ReadonlyKeyword &&\n (node.getTypeNode().isKind(tsm.SyntaxKind.ArrayType) || // Use optional chaining and isKind\n node.getTypeNode().isKind(tsm.SyntaxKind.TupleType));\n\nexport type ReadonlyArrayTypeNode = tsm.TypeNode &\n
|
|
1
|
+
{"version":3,"file":"is-readonly-node.mjs","sources":["../../../src/functions/functions/is-readonly-node.mts"],"sourcesContent":["import { Arr, expectType } from 'ts-data-forge';\nimport * as tsm from 'ts-morph';\nimport { type DeepReadonly, type StrictOmit } from 'ts-type-forge';\nimport { isAtomicTypeNode } from './is-atomic-type-node.mjs';\n\nexport const isShallowReadonlyTypeNode = (node: tsm.Node): boolean =>\n isReadonlyTupleOrArrayTypeNode(node) ||\n isReadonlyTypeReferenceNode(node) ||\n isAtomicTypeNode(node);\n\nexport const isReadonlyTupleOrArrayTypeNode = (\n node: DeepReadonly<tsm.Node>,\n): node is ReadonlyArrayTypeNode | ReadonlyTupleTypeNode =>\n node.isKind(tsm.SyntaxKind.TypeOperator) &&\n node.getOperator() === tsm.SyntaxKind.ReadonlyKeyword &&\n (node.getTypeNode().isKind(tsm.SyntaxKind.ArrayType) || // Use optional chaining and isKind\n node.getTypeNode().isKind(tsm.SyntaxKind.TupleType));\n\nexport type ReadonlyArrayTypeNode = tsm.TypeNode &\n StrictOmit<tsm.TypeOperatorTypeNode, 'getOperator' | 'getTypeNode'> &\n Readonly<{\n getOperator: () => tsm.SyntaxKind.ReadonlyKeyword;\n getTypeNode: () => tsm.ArrayTypeNode;\n }>;\n\nexport const isReadonlyArrayTypeNode = (\n node: DeepReadonly<tsm.Node>,\n): node is ReadonlyArrayTypeNode =>\n node.isKind(tsm.SyntaxKind.TypeOperator) &&\n node.getOperator() === tsm.SyntaxKind.ReadonlyKeyword &&\n node.getTypeNode().isKind(tsm.SyntaxKind.ArrayType);\n\n// Helper to get a specific type node from source code\nconst getTypeNodeFromSource = (\n sourceCode: string,\n typeName: string,\n): tsm.Node => {\n const project = new tsm.Project({ useInMemoryFileSystem: true });\n\n const sourceFile = project.createSourceFile('test.ts', sourceCode);\n\n const typeAlias = sourceFile.getTypeAliasOrThrow(typeName);\n\n return typeAlias.getTypeNodeOrThrow();\n};\n\nif (import.meta.vitest !== undefined) {\n describe('isReadonlyArrayTypeNode', () => {\n test('should return true for readonly array type', () => {\n const node = getTypeNodeFromSource(\n 'type Test = readonly number[];',\n 'Test',\n );\n\n if (isReadonlyArrayTypeNode(node)) {\n const _operator = node.getOperator();\n\n expectType<typeof _operator, tsm.SyntaxKind.ReadonlyKeyword>('=');\n\n const _typeNode = node.getTypeNode();\n\n expectType<typeof _typeNode, tsm.ArrayTypeNode>('=');\n }\n\n assert.isTrue(node.isKind(tsm.SyntaxKind.TypeOperator));\n\n if (!isReadonlyArrayTypeNode(node)) {\n throw new Error('node should be ReadonlyArrayTypeNode');\n }\n\n expect(node.getOperator()).toBe(tsm.SyntaxKind.ReadonlyKeyword);\n\n assert.isTrue(node.getTypeNode().isKind(tsm.SyntaxKind.ArrayType));\n });\n\n test('should return false for non-readonly array', () => {\n const node = getTypeNodeFromSource('type Test = string[];', 'Test');\n\n assert.isFalse(isReadonlyArrayTypeNode(node));\n });\n\n test('should return false for readonly tuple', () => {\n const node = getTypeNodeFromSource(\n 'type Test = readonly [string];',\n 'Test',\n );\n\n assert.isFalse(isReadonlyArrayTypeNode(node));\n });\n });\n}\n\nexport type ReadonlyTupleTypeNode = tsm.TypeNode &\n StrictOmit<tsm.TypeOperatorTypeNode, 'getOperator' | 'getTypeNode'> &\n Readonly<{\n getOperator: () => tsm.SyntaxKind.ReadonlyKeyword;\n getTypeNode: () => tsm.TupleTypeNode;\n }>;\n\nexport const isReadonlyTupleTypeNode = (\n node: DeepReadonly<tsm.Node>,\n): node is ReadonlyTupleTypeNode =>\n node.isKind(tsm.SyntaxKind.TypeOperator) &&\n node.getOperator() === tsm.SyntaxKind.ReadonlyKeyword &&\n node.getTypeNode().isKind(tsm.SyntaxKind.TupleType);\n\nif (import.meta.vitest !== undefined) {\n describe('isReadonlyTupleTypeNode', () => {\n test('should return true for readonly tuple type', () => {\n const node = getTypeNodeFromSource(\n 'type Test = readonly [number, string];',\n 'Test',\n );\n\n assert.isTrue(isReadonlyTupleTypeNode(node));\n\n if (isReadonlyTupleTypeNode(node)) {\n const _operator = node.getOperator();\n\n expectType<typeof _operator, tsm.SyntaxKind.ReadonlyKeyword>('=');\n\n const _typeNode = node.getTypeNode();\n\n expectType<typeof _typeNode, tsm.TupleTypeNode>('=');\n }\n\n assert.isTrue(node.isKind(tsm.SyntaxKind.TypeOperator));\n\n if (!isReadonlyTupleTypeNode(node)) {\n throw new Error('node should be ReadonlyTupleTypeNode');\n }\n\n expect(node.getOperator()).toBe(tsm.SyntaxKind.ReadonlyKeyword);\n\n assert.isTrue(node.getTypeNode().isKind(tsm.SyntaxKind.TupleType));\n });\n\n test('should return false for non-readonly tuple', () => {\n const node = getTypeNodeFromSource('type Test = [boolean];', 'Test');\n\n assert.isFalse(isReadonlyTupleTypeNode(node));\n });\n\n test('should return false for readonly array', () => {\n const node = getTypeNodeFromSource(\n 'type Test = readonly number[];',\n 'Test',\n );\n\n assert.isFalse(isReadonlyTupleTypeNode(node));\n });\n });\n}\n\nexport type ReadonlyTypeReferenceNode = tsm.TypeNode &\n StrictOmit<tsm.TypeReferenceNode, 'getTypeName' | 'getTypeArguments'> &\n Readonly<{\n getTypeName: () => StrictOmit<tsm.Identifier, 'getText'> &\n Readonly<{\n getText: () => 'Readonly';\n }>;\n getTypeArguments: () => readonly [tsm.TypeNode];\n }>;\n\nexport const isReadonlyTypeReferenceNode = (\n node: DeepReadonly<tsm.Node>,\n): node is ReadonlyTypeReferenceNode => {\n if (!node.isKind(tsm.SyntaxKind.TypeReference)) {\n return false;\n }\n\n const typeName = node.getTypeName();\n\n const typeArguments = node.getTypeArguments();\n\n return (\n typeName.isKind(tsm.SyntaxKind.Identifier) &&\n typeName.getText() === 'Readonly' &&\n Arr.isFixedLengthArray(1, typeArguments)\n );\n};\n\nif (import.meta.vitest !== undefined) {\n describe('isReadonlyTypeReferenceNode', () => {\n test('should return true for Readonly<T>', () => {\n const node = getTypeNodeFromSource(\n 'type Test = Readonly<{ x: number }>;',\n 'Test',\n );\n\n assert.isTrue(isReadonlyTypeReferenceNode(node));\n\n if (isReadonlyTypeReferenceNode(node)) {\n const _typeNameText = node.getTypeName().getText();\n\n expectType<typeof _typeNameText, 'Readonly'>('=');\n\n const _typeArguments = node.getTypeArguments();\n\n expectType<\n typeof _typeArguments,\n readonly [tsm.TypeNode<tsm.ts.TypeNode>]\n >('=');\n }\n\n assert.isTrue(node.isKind(tsm.SyntaxKind.TypeReference));\n\n if (!isReadonlyTypeReferenceNode(node)) {\n throw new Error('node should be ReadonlyNode');\n }\n\n expect(node.getTypeName().getText()).toBe('Readonly');\n\n expect(node.getTypeArguments()).toHaveLength(1);\n });\n\n test('should return false for other type references', () => {\n const node = getTypeNodeFromSource(\n 'type Test = Partial<{ y: string }>;',\n 'Test',\n );\n\n assert.isFalse(isReadonlyTypeReferenceNode(node));\n });\n\n test('should return false for Readonly without type arguments', () => {\n // Note: This is syntactically incorrect TS, but testing the guard\n const node = getTypeNodeFromSource('type Test = Readonly;', 'Test');\n\n assert.isFalse(isReadonlyTypeReferenceNode(node));\n });\n\n test('should return false for Readonly with multiple type arguments', () => {\n // Note: This is syntactically incorrect TS, but testing the guard\n const project = new tsm.Project({ useInMemoryFileSystem: true });\n\n // Need to create manually as TS parser might reject Readonly<A, B>\n const sourceFile = project.createSourceFile(\n 'test.ts',\n 'type Test = Readonly<string, number>;',\n );\n\n const node = sourceFile.getTypeAliasOrThrow('Test').getTypeNodeOrThrow();\n\n assert.isFalse(isReadonlyTypeReferenceNode(node));\n });\n });\n}\n"],"names":[],"mappings":";;;;MAKa,yBAAA,GAA4B,CAAC,IAAA,KACxC,8BAAA,CAA+B,IAAI,KACnC,2BAAA,CAA4B,IAAI,CAAA,IAChC,gBAAA,CAAiB,IAAI;MAEV,8BAAA,GAAiC,CAC5C,IAAA,KAEA,IAAA,CAAK,OAAO,GAAA,CAAI,UAAA,CAAW,YAAY,CAAA,IACvC,IAAA,CAAK,aAAY,KAAM,GAAA,CAAI,WAAW,eAAA,KACrC,IAAA,CAAK,aAAY,CAAE,MAAA,CAAO,GAAA,CAAI,UAAA,CAAW,SAAS,CAAA;AACjD,IAAA,CAAK,WAAA,EAAY,CAAE,MAAA,CAAO,GAAA,CAAI,WAAW,SAAS,CAAA;MASzC,uBAAA,GAA0B,CACrC,IAAA,KAEA,IAAA,CAAK,OAAO,GAAA,CAAI,UAAA,CAAW,YAAY,CAAA,IACvC,IAAA,CAAK,aAAY,KAAM,GAAA,CAAI,WAAW,eAAA,IACtC,IAAA,CAAK,aAAY,CAAE,MAAA,CAAO,GAAA,CAAI,UAAA,CAAW,SAAS;MAqEvC,uBAAA,GAA0B,CACrC,IAAA,KAEA,IAAA,CAAK,OAAO,GAAA,CAAI,UAAA,CAAW,YAAY,CAAA,IACvC,IAAA,CAAK,aAAY,KAAM,GAAA,CAAI,WAAW,eAAA,IACtC,IAAA,CAAK,aAAY,CAAE,MAAA,CAAO,GAAA,CAAI,UAAA,CAAW,SAAS;AA4D7C,MAAM,2BAAA,GAA8B,CACzC,IAAA,KACsC;AACtC,EAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,UAAA,CAAW,aAAa,CAAA,EAAG;AAC9C,IAAA,OAAO,KAAA;AAAA,EAAA;AAGT,EAAA,MAAM,QAAA,GAAW,KAAK,WAAA,EAAY;AAElC,EAAA,MAAM,aAAA,GAAgB,KAAK,gBAAA,EAAiB;AAE5C,EAAA,OACE,QAAA,CAAS,MAAA,CAAO,GAAA,CAAI,UAAA,CAAW,UAAU,CAAA,IACzC,QAAA,CAAS,OAAA,EAAQ,KAAM,UAAA,IACvB,GAAA,CAAI,kBAAA,CAAmB,GAAG,aAAa,CAAA;AAE3C;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"should-avoid-parentheses-for-readonly.d.mts","sourceRoot":"","sources":["../../../src/functions/functions/should-avoid-parentheses-for-readonly.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAEhC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iCAAiC,SAAU,GAAG,CAAC,IAAI,KAAG,
|
|
1
|
+
{"version":3,"file":"should-avoid-parentheses-for-readonly.d.mts","sourceRoot":"","sources":["../../../src/functions/functions/should-avoid-parentheses-for-readonly.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAEhC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iCAAiC,SAAU,GAAG,CAAC,IAAI,KAAG,OAYlE,CAAC"}
|
|
@@ -5,10 +5,7 @@ const shouldAvoidParenthesesForReadonly = (node) => {
|
|
|
5
5
|
if (parent === void 0) {
|
|
6
6
|
return false;
|
|
7
7
|
}
|
|
8
|
-
|
|
9
|
-
return true;
|
|
10
|
-
}
|
|
11
|
-
return false;
|
|
8
|
+
return parent.isKind(tsm.SyntaxKind.TypePredicate);
|
|
12
9
|
};
|
|
13
10
|
|
|
14
11
|
export { shouldAvoidParenthesesForReadonly };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"should-avoid-parentheses-for-readonly.mjs","sources":["../../../src/functions/functions/should-avoid-parentheses-for-readonly.mts"],"sourcesContent":["import * as tsm from 'ts-morph';\n\n/**\n * Determines if parentheses should be avoided when adding 'readonly' prefix to a type.\n *\n * Parentheses should be AVOIDED in these specific contexts:\n * - Type predicates: `x is [T, U]` -> `x is readonly [T, U]` (not `x is (readonly [T, U])`)\n * because parentheses around the type in a type predicate cause syntax errors\n *\n * For all other contexts, we keep parentheses for safety to avoid precedence issues,\n * relying on prettier to remove unnecessary ones.\n *\n * @param node - The type node to check\n * @returns true if parentheses should be avoided, false otherwise (keep parentheses)\n */\nexport const shouldAvoidParenthesesForReadonly = (node: tsm.Node): boolean => {\n const parent = node.getParent();\n\n if (parent === undefined) {\n return false;\n }\n\n // Check if parent is TypePredicate: x is T\n // In this case, we MUST avoid parentheses: x is readonly T (not x is (readonly T))\n // because `x is (readonly T)` is a syntax error\n
|
|
1
|
+
{"version":3,"file":"should-avoid-parentheses-for-readonly.mjs","sources":["../../../src/functions/functions/should-avoid-parentheses-for-readonly.mts"],"sourcesContent":["import * as tsm from 'ts-morph';\n\n/**\n * Determines if parentheses should be avoided when adding 'readonly' prefix to a type.\n *\n * Parentheses should be AVOIDED in these specific contexts:\n * - Type predicates: `x is [T, U]` -> `x is readonly [T, U]` (not `x is (readonly [T, U])`)\n * because parentheses around the type in a type predicate cause syntax errors\n *\n * For all other contexts, we keep parentheses for safety to avoid precedence issues,\n * relying on prettier to remove unnecessary ones.\n *\n * @param node - The type node to check\n * @returns true if parentheses should be avoided, false otherwise (keep parentheses)\n */\nexport const shouldAvoidParenthesesForReadonly = (node: tsm.Node): boolean => {\n const parent = node.getParent();\n\n if (parent === undefined) {\n return false;\n }\n\n // Check if parent is TypePredicate: x is T\n // In this case, we MUST avoid parentheses: x is readonly T (not x is (readonly T))\n // because `x is (readonly T)` is a syntax error\n // For all other cases, keep parentheses for safety\n return parent.isKind(tsm.SyntaxKind.TypePredicate);\n};\n"],"names":[],"mappings":";;AAeO,MAAM,iCAAA,GAAoC,CAAC,IAAA,KAA4B;AAC5E,EAAA,MAAM,MAAA,GAAS,KAAK,SAAA,EAAU;AAE9B,EAAA,IAAI,WAAW,MAAA,EAAW;AACxB,IAAA,OAAO,KAAA;AAAA,EACT;AAMA,EAAA,OAAO,MAAA,CAAO,MAAA,CAAO,GAAA,CAAI,UAAA,CAAW,aAAa,CAAA;AACnD;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-codemod-lib",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -11,13 +11,11 @@
|
|
|
11
11
|
],
|
|
12
12
|
"repository": {
|
|
13
13
|
"type": "git",
|
|
14
|
-
"url": "git+https://github.com/noshiro-pf/
|
|
14
|
+
"url": "git+https://github.com/noshiro-pf/mono.git",
|
|
15
|
+
"directory": "libs/ts-codemod-lib"
|
|
15
16
|
},
|
|
16
17
|
"license": "Apache-2.0",
|
|
17
18
|
"author": "noshiro-pf <noshiro.pf@gmail.com>",
|
|
18
|
-
"sideEffects": [
|
|
19
|
-
"./dist/cmd/*.mjs"
|
|
20
|
-
],
|
|
21
19
|
"type": "module",
|
|
22
20
|
"exports": {
|
|
23
21
|
".": {
|
|
@@ -33,144 +31,49 @@
|
|
|
33
31
|
},
|
|
34
32
|
"module": "./dist/entry-point.mjs",
|
|
35
33
|
"types": "./dist/types.d.mts",
|
|
36
|
-
"bin": {
|
|
37
|
-
"append-as-const": "./dist/cmd/append-as-const.mjs",
|
|
38
|
-
"convert-interface-to-type": "./dist/cmd/convert-interface-to-type.mjs",
|
|
39
|
-
"convert-to-readonly": "./dist/cmd/convert-to-readonly.mjs",
|
|
40
|
-
"replace-any-with-unknown": "./dist/cmd/replace-any-with-unknown.mjs",
|
|
41
|
-
"replace-record-with-unknown-record": "./dist/cmd/replace-record-with-unknown-record.mjs"
|
|
42
|
-
},
|
|
43
34
|
"files": [
|
|
44
35
|
"src",
|
|
45
36
|
"dist",
|
|
46
37
|
"README.md",
|
|
47
38
|
"LICENSE"
|
|
48
39
|
],
|
|
49
|
-
"scripts": {
|
|
50
|
-
"agents:gen": "tsx ./scripts/cmd/gen-agents-md.mts",
|
|
51
|
-
"agents:sync": "tsx ./scripts/cmd/sync-agent-config.mts",
|
|
52
|
-
"build": "tsx ./scripts/cmd/build.mts",
|
|
53
|
-
"build:min": "tsx ./scripts/cmd/build.mts --skip-check",
|
|
54
|
-
"check-all": "tsx ./scripts/cmd/check-all.mts",
|
|
55
|
-
"check:ext": "tsx ./scripts/cmd/check-ext.mts",
|
|
56
|
-
"clean": "pnpm run /clean:.*/",
|
|
57
|
-
"clean:logs": "npx rimraf ./*.log",
|
|
58
|
-
"codemod": "run-s codemod:uncommitted:* fmt",
|
|
59
|
-
"codemod:diff": "run-s codemod:diff:* fmt",
|
|
60
|
-
"codemod:diff:any-to-unknown": "tsx ./src/cmd/replace-any-with-unknown.mts --diff-from origin/main '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
61
|
-
"codemod:diff:as-const": "tsx ./src/cmd/append-as-const.mts --diff-from origin/main '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
62
|
-
"codemod:diff:interface-to-type": "tsx ./src/cmd/convert-interface-to-type.mts --diff-from origin/main '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
63
|
-
"codemod:diff:readonly": "tsx ./src/cmd/convert-to-readonly.mts --diff-from origin/main '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
64
|
-
"codemod:diff:unknown-record": "tsx ./src/cmd/replace-record-with-unknown-record.mts --diff-from origin/main '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
65
|
-
"codemod:full": "run-s codemod:full:* fmt",
|
|
66
|
-
"codemod:full:any-to-unknown": "tsx ./src/cmd/replace-any-with-unknown.mts '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
67
|
-
"codemod:full:as-const": "tsx ./src/cmd/append-as-const.mts '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
68
|
-
"codemod:full:interface-to-type": "tsx ./src/cmd/convert-interface-to-type.mts '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
69
|
-
"codemod:full:readonly": "tsx ./src/cmd/convert-to-readonly.mts '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
70
|
-
"codemod:full:unknown-record": "tsx ./src/cmd/replace-record-with-unknown-record.mts '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
71
|
-
"codemod:uncommitted:any-to-unknown": "tsx ./src/cmd/replace-any-with-unknown.mts --uncommitted '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
72
|
-
"codemod:uncommitted:as-const": "tsx ./src/cmd/append-as-const.mts --uncommitted '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
73
|
-
"codemod:uncommitted:interface-to-type": "tsx ./src/cmd/convert-interface-to-type.mts --uncommitted '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
74
|
-
"codemod:uncommitted:readonly": "tsx ./src/cmd/convert-to-readonly.mts --uncommitted '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
75
|
-
"codemod:uncommitted:unknown-record": "tsx ./src/cmd/replace-record-with-unknown-record.mts --uncommitted '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
76
|
-
"cspell": "cspell \"{**,.changeset/**/*,.github/**/*}\" --gitignore --gitignore-root ./ --no-progress",
|
|
77
|
-
"doc": "tsx ./scripts/cmd/gen-docs.mts",
|
|
78
|
-
"doc:embed": "tsx ./scripts/cmd/embed-examples.mts",
|
|
79
|
-
"doc:preview": "vite preview --config ./configs/vite.doc.config.mts",
|
|
80
|
-
"doc:watch": "typedoc --options ./configs/typedoc.config.mjs --watch",
|
|
81
|
-
"fmt": "format-uncommitted",
|
|
82
|
-
"fmt:diff": "format-diff-from origin/main",
|
|
83
|
-
"fmt:full": "prettier --write .",
|
|
84
|
-
"gi": "run-s gi:src fmt",
|
|
85
|
-
"gi:src": "gen-index-ts ./src --index-ext .mts --export-ext .mjs --target-ext .mts --target-ext .tsx --exclude entry-point.mts --exclude cmd",
|
|
86
|
-
"lint": "eslint .",
|
|
87
|
-
"lint:fix": "eslint . --fix",
|
|
88
|
-
"md": "markdownlint-cli2",
|
|
89
|
-
"prepare-release": "run-s sync-cli-versions fmt build doc",
|
|
90
|
-
"repo-settings:apply": "repo-settings apply",
|
|
91
|
-
"repo-settings:backup": "repo-settings backup",
|
|
92
|
-
"run:cmd": "tsx ./src/cmd/convert-to-readonly.mts ./test/sample1.mts",
|
|
93
|
-
"run:test": "tsx ./scripts/test-code/transform-test-code.mts",
|
|
94
|
-
"sync-cli-versions": "tsx scripts/cmd/sync-cli-versions.mts",
|
|
95
|
-
"test": "pnpm run z:vitest:node run",
|
|
96
|
-
"test:browser": "pnpm run z:vitest --project='Browser' run",
|
|
97
|
-
"test:cov": "pnpm run z:vitest:node run --coverage",
|
|
98
|
-
"test:cov:ui": "vite preview --outDir ./coverage",
|
|
99
|
-
"test:ui": "pnpm run z:vitest:node --ui",
|
|
100
|
-
"testw": "pnpm run z:vitest:node watch",
|
|
101
|
-
"tsc": "node ./node_modules/typescript-native/bin/tsc --noEmit",
|
|
102
|
-
"tscw": "node ./node_modules/typescript-native/bin/tsc --noEmit --watch -p ./tsconfig.json",
|
|
103
|
-
"type-check": "node ./node_modules/typescript-native/bin/tsc --noEmit",
|
|
104
|
-
"z:vitest": "vitest --config ./configs/vitest.config.mts",
|
|
105
|
-
"z:vitest:node": "pnpm run z:vitest --project='Node.js'"
|
|
106
|
-
},
|
|
107
40
|
"dependencies": {
|
|
108
|
-
"ts-data-forge": "^14.0.0",
|
|
109
41
|
"ts-morph": "^28.0.0",
|
|
110
|
-
"ts-
|
|
42
|
+
"ts-data-forge": "^14.2.1",
|
|
43
|
+
"ts-type-forge": "^9.2.1"
|
|
111
44
|
},
|
|
112
45
|
"devDependencies": {
|
|
113
46
|
"@rollup/plugin-replace": "6.0.3",
|
|
114
47
|
"@rollup/plugin-strip": "3.0.4",
|
|
115
|
-
"@
|
|
116
|
-
"@semantic-release/commit-analyzer": "13.0.1",
|
|
117
|
-
"@semantic-release/exec": "7.1.0",
|
|
118
|
-
"@semantic-release/git": "11.0.1",
|
|
119
|
-
"@semantic-release/github": "12.0.9",
|
|
120
|
-
"@semantic-release/npm": "13.1.5",
|
|
121
|
-
"@semantic-release/release-notes-generator": "14.1.1",
|
|
122
|
-
"@types/node": "26.1.2",
|
|
48
|
+
"@types/node": "26.2.0",
|
|
123
49
|
"@vitest/browser-playwright": "4.1.10",
|
|
124
50
|
"@vitest/coverage-v8": "4.1.10",
|
|
125
51
|
"@vitest/ui": "4.1.10",
|
|
126
|
-
"cmd-ts": "0.15.0",
|
|
127
|
-
"conventional-changelog-conventionalcommits": "10.2.1",
|
|
128
52
|
"cspell": "10.0.1",
|
|
129
53
|
"dedent": "1.7.2",
|
|
130
54
|
"esbuild": "0.28.1",
|
|
131
55
|
"eslint": "10.8.0",
|
|
132
|
-
"eslint-config-typed": "5.8.2",
|
|
133
|
-
"eslint-plugin-ts-data-forge": "0.3.0",
|
|
134
|
-
"eslint-plugin-ts-fortress": "0.4.0",
|
|
135
|
-
"eslint-plugin-ts-type-forge": "0.4.3",
|
|
136
|
-
"github-settings-as-code": "2.0.1",
|
|
137
56
|
"jiti": "2.7.0",
|
|
138
|
-
"
|
|
139
|
-
"
|
|
140
|
-
"npm-run-all2": "9.0.2",
|
|
141
|
-
"playwright": "1.62.0",
|
|
57
|
+
"npm-run-all2": "9.0.3",
|
|
58
|
+
"playwright": "1.62.1",
|
|
142
59
|
"prettier": "3.9.6",
|
|
143
60
|
"prettier-plugin-organize-imports": "4.3.0",
|
|
144
61
|
"prettier-plugin-packagejson": "3.0.2",
|
|
145
|
-
"rollup": "4.62.
|
|
62
|
+
"rollup": "4.62.4",
|
|
146
63
|
"rollup-plugin-esbuild": "6.2.1",
|
|
147
|
-
"
|
|
148
|
-
"ts-repo-utils": "10.1.6",
|
|
149
|
-
"tsx": "4.23.1",
|
|
64
|
+
"tsx": "4.23.4",
|
|
150
65
|
"typedoc": "0.28.20",
|
|
151
66
|
"typedoc-github-theme": "0.4.0",
|
|
152
67
|
"typescript": "6.0.3",
|
|
153
68
|
"typescript-native": "npm:typescript@7.0.2",
|
|
154
|
-
"vite": "8.
|
|
155
|
-
"vitest": "4.1.10"
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
"
|
|
159
|
-
"
|
|
160
|
-
"ts-repo-utils": "
|
|
161
|
-
},
|
|
162
|
-
"peerDependenciesMeta": {
|
|
163
|
-
"cmd-ts": {
|
|
164
|
-
"optional": true
|
|
165
|
-
},
|
|
166
|
-
"dedent": {
|
|
167
|
-
"optional": true
|
|
168
|
-
},
|
|
169
|
-
"ts-repo-utils": {
|
|
170
|
-
"optional": true
|
|
171
|
-
}
|
|
69
|
+
"vite": "8.2.0",
|
|
70
|
+
"vitest": "4.1.10",
|
|
71
|
+
"eslint-config-typed": "5.8.5",
|
|
72
|
+
"eslint-plugin-ts-data-forge": "0.4.4",
|
|
73
|
+
"eslint-plugin-ts-fortress": "1.0.1",
|
|
74
|
+
"eslint-plugin-ts-type-forge": "0.6.3",
|
|
75
|
+
"ts-repo-utils": "10.2.0"
|
|
172
76
|
},
|
|
173
|
-
"packageManager": "pnpm@11.20.0",
|
|
174
77
|
"engines": {
|
|
175
78
|
"node": ">=22.22.2",
|
|
176
79
|
"pnpm": ">=9.0.0"
|
|
@@ -181,5 +84,56 @@
|
|
|
181
84
|
"publishConfig": {
|
|
182
85
|
"access": "public",
|
|
183
86
|
"provenance": true
|
|
87
|
+
},
|
|
88
|
+
"scripts": {
|
|
89
|
+
"build": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ./scripts/cmd/build.mts",
|
|
90
|
+
"build:min": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ./scripts/cmd/build.mts --skip-check",
|
|
91
|
+
"check-all": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ./scripts/cmd/check-all.mts",
|
|
92
|
+
"check:ext": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ./scripts/cmd/check-ext.mts",
|
|
93
|
+
"clean": "pnpm run /clean:.*/",
|
|
94
|
+
"clean:logs": "npx rimraf ./*.log",
|
|
95
|
+
"codemod": "run-s codemod:uncommitted:* fmt",
|
|
96
|
+
"codemod:diff": "run-s codemod:diff:* fmt",
|
|
97
|
+
"codemod:diff:any-to-unknown": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../ts-codemod-cli/src/cmd/replace-any-with-unknown.mts --diff-from origin/main '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
98
|
+
"codemod:diff:as-const": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../ts-codemod-cli/src/cmd/append-as-const.mts --diff-from origin/main '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
99
|
+
"codemod:diff:interface-to-type": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../ts-codemod-cli/src/cmd/convert-interface-to-type.mts --diff-from origin/main '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
100
|
+
"codemod:diff:readonly": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../ts-codemod-cli/src/cmd/convert-to-readonly.mts --diff-from origin/main '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
101
|
+
"codemod:diff:unknown-record": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../ts-codemod-cli/src/cmd/replace-record-with-unknown-record.mts --diff-from origin/main '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
102
|
+
"codemod:full": "run-s codemod:full:* fmt",
|
|
103
|
+
"codemod:full:any-to-unknown": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../ts-codemod-cli/src/cmd/replace-any-with-unknown.mts '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
104
|
+
"codemod:full:as-const": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../ts-codemod-cli/src/cmd/append-as-const.mts '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
105
|
+
"codemod:full:interface-to-type": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../ts-codemod-cli/src/cmd/convert-interface-to-type.mts '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
106
|
+
"codemod:full:readonly": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../ts-codemod-cli/src/cmd/convert-to-readonly.mts '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
107
|
+
"codemod:full:unknown-record": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../ts-codemod-cli/src/cmd/replace-record-with-unknown-record.mts '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
108
|
+
"codemod:uncommitted:any-to-unknown": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../ts-codemod-cli/src/cmd/replace-any-with-unknown.mts --uncommitted '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
109
|
+
"codemod:uncommitted:as-const": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../ts-codemod-cli/src/cmd/append-as-const.mts --uncommitted '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
110
|
+
"codemod:uncommitted:interface-to-type": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../ts-codemod-cli/src/cmd/convert-interface-to-type.mts --uncommitted '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
111
|
+
"codemod:uncommitted:readonly": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../ts-codemod-cli/src/cmd/convert-to-readonly.mts --uncommitted '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
112
|
+
"codemod:uncommitted:unknown-record": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../ts-codemod-cli/src/cmd/replace-record-with-unknown-record.mts --uncommitted '{src,scripts,samples,test}/**/*.{mts,tsx}'",
|
|
113
|
+
"cspell": "cspell \"**\" --gitignore --gitignore-root ../../ --no-progress",
|
|
114
|
+
"doc": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ./scripts/cmd/gen-docs.mts",
|
|
115
|
+
"doc:embed": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ./scripts/cmd/embed-examples.mts",
|
|
116
|
+
"doc:preview": "vite preview --config ./configs/vite.doc.config.mts",
|
|
117
|
+
"doc:watch": "typedoc --options ./configs/typedoc.config.mjs --watch",
|
|
118
|
+
"fmt": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../../libs/ts-repo-utils/src/cmd/format-uncommitted.mts --cwd .",
|
|
119
|
+
"fmt:diff": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../../libs/ts-repo-utils/src/cmd/format-diff-from.mts origin/main --cwd .",
|
|
120
|
+
"fmt:full": "prettier --write .",
|
|
121
|
+
"gi": "run-s gi:src fmt",
|
|
122
|
+
"gi:src": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../../libs/ts-repo-utils/src/cmd/gen-index-ts.mts ./src --index-ext .mts --export-ext .mjs --target-ext .mts --target-ext .tsx --exclude entry-point.mts",
|
|
123
|
+
"lint": "eslint .",
|
|
124
|
+
"lint:fix": "eslint . --fix",
|
|
125
|
+
"prepare-release": "run-s fmt build doc",
|
|
126
|
+
"run:test": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ./scripts/test-code/transform-test-code.mts",
|
|
127
|
+
"test": "pnpm run z:vitest:node run",
|
|
128
|
+
"test:browser": "pnpm run z:vitest --project='Browser' run",
|
|
129
|
+
"test:cov": "pnpm run z:vitest:node run --coverage",
|
|
130
|
+
"test:cov:ui": "vite preview --outDir ./coverage",
|
|
131
|
+
"test:ui": "pnpm run z:vitest:node --ui",
|
|
132
|
+
"testw": "pnpm run z:vitest:node watch",
|
|
133
|
+
"tsc": "node ../../node_modules/typescript-native/bin/tsc --noEmit",
|
|
134
|
+
"tscw": "node ../../node_modules/typescript-native/bin/tsc --noEmit --watch -p ./tsconfig.json",
|
|
135
|
+
"type-check": "node ../../node_modules/typescript-native/bin/tsc --noEmit",
|
|
136
|
+
"z:vitest": "vitest --config ./configs/vitest.config.mts",
|
|
137
|
+
"z:vitest:node": "pnpm run z:vitest --project='Node.js'"
|
|
184
138
|
}
|
|
185
|
-
}
|
|
139
|
+
}
|
|
@@ -8,7 +8,12 @@ import {
|
|
|
8
8
|
pipe,
|
|
9
9
|
} from 'ts-data-forge';
|
|
10
10
|
import * as tsm from 'ts-morph';
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
type DeepReadonly,
|
|
13
|
+
type SafeUintWithSmallInt,
|
|
14
|
+
type StrictExclude,
|
|
15
|
+
type StrictExtract,
|
|
16
|
+
} from 'ts-type-forge';
|
|
12
17
|
import {
|
|
13
18
|
hasDisableNextLineComment,
|
|
14
19
|
isAtomicTypeNode,
|
|
@@ -397,7 +402,7 @@ const transformNode = (
|
|
|
397
402
|
const transformTypeReferenceNode = (
|
|
398
403
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
399
404
|
node: tsm.TypeReferenceNode,
|
|
400
|
-
readonlyContext:
|
|
405
|
+
readonlyContext: StrictExclude<
|
|
401
406
|
ReadonlyContext,
|
|
402
407
|
Readonly<{ type: 'readonly'; indexedAccessDepth: SafeUintWithSmallInt }>
|
|
403
408
|
>,
|
|
@@ -813,7 +818,7 @@ const transformRestTypeNode = (
|
|
|
813
818
|
const transformTypeOperatorNode = (
|
|
814
819
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
815
820
|
node: tsm.TypeOperatorTypeNode,
|
|
816
|
-
readonlyContext:
|
|
821
|
+
readonlyContext: StrictExclude<
|
|
817
822
|
ReadonlyContext,
|
|
818
823
|
Readonly<{ type: 'readonly'; indexedAccessDepth: SafeUintWithSmallInt }>
|
|
819
824
|
>,
|
|
@@ -852,7 +857,7 @@ const transformTypeOperatorNode = (
|
|
|
852
857
|
const transformTypeLiteralNode = (
|
|
853
858
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
854
859
|
node: tsm.TypeLiteralNode,
|
|
855
|
-
readonlyContext:
|
|
860
|
+
readonlyContext: StrictExclude<
|
|
856
861
|
ReadonlyContext,
|
|
857
862
|
Readonly<{ type: 'readonly'; indexedAccessDepth: SafeUintWithSmallInt }>
|
|
858
863
|
>,
|
|
@@ -927,7 +932,7 @@ const transformIndexedAccessTypeNode = (
|
|
|
927
932
|
const transformMappedTypeNode = (
|
|
928
933
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
929
934
|
node: tsm.MappedTypeNode,
|
|
930
|
-
readonlyContext:
|
|
935
|
+
readonlyContext: StrictExclude<
|
|
931
936
|
ReadonlyContext,
|
|
932
937
|
Readonly<{ type: 'readonly'; indexedAccessDepth: SafeUintWithSmallInt }>
|
|
933
938
|
>,
|
|
@@ -1109,7 +1114,7 @@ const transformConstructorParameter = (
|
|
|
1109
1114
|
const transformIntersectionTypeNode = (
|
|
1110
1115
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
1111
1116
|
node: tsm.IntersectionTypeNode,
|
|
1112
|
-
readonlyContext:
|
|
1117
|
+
readonlyContext: StrictExclude<
|
|
1113
1118
|
ReadonlyContext,
|
|
1114
1119
|
Readonly<{ type: 'readonly'; indexedAccessDepth: SafeUintWithSmallInt }>
|
|
1115
1120
|
>,
|
|
@@ -1125,7 +1130,7 @@ const transformIntersectionTypeNode = (
|
|
|
1125
1130
|
const transformUnionTypeNode = (
|
|
1126
1131
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
1127
1132
|
node: tsm.UnionTypeNode,
|
|
1128
|
-
readonlyContext:
|
|
1133
|
+
readonlyContext: StrictExclude<
|
|
1129
1134
|
ReadonlyContext,
|
|
1130
1135
|
Readonly<{ type: 'readonly'; indexedAccessDepth: SafeUintWithSmallInt }>
|
|
1131
1136
|
>,
|
|
@@ -1137,7 +1142,7 @@ const transformUnionTypeNode = (
|
|
|
1137
1142
|
const transformUnionOrIntersectionTypeNodeImpl = (
|
|
1138
1143
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
1139
1144
|
node: tsm.IntersectionTypeNode | tsm.UnionTypeNode,
|
|
1140
|
-
readonlyContext:
|
|
1145
|
+
readonlyContext: StrictExclude<
|
|
1141
1146
|
ReadonlyContext,
|
|
1142
1147
|
Readonly<{ type: 'readonly'; indexedAccessDepth: SafeUintWithSmallInt }>
|
|
1143
1148
|
>,
|
|
@@ -1346,7 +1351,7 @@ const transformMembers = (
|
|
|
1346
1351
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
1347
1352
|
members: readonly tsm.TypeElementTypes[],
|
|
1348
1353
|
readonlyModifier: 'add' | 'remove',
|
|
1349
|
-
readonlyContext:
|
|
1354
|
+
readonlyContext: StrictExtract<
|
|
1350
1355
|
ReadonlyContext,
|
|
1351
1356
|
Readonly<{
|
|
1352
1357
|
type: 'DeepReadonly' | 'none';
|
|
@@ -1387,8 +1392,6 @@ const transformMembers = (
|
|
|
1387
1392
|
}
|
|
1388
1393
|
|
|
1389
1394
|
transformNode(mb, readonlyContext, options);
|
|
1390
|
-
|
|
1391
|
-
continue;
|
|
1392
1395
|
}
|
|
1393
1396
|
};
|
|
1394
1397
|
|
|
@@ -1396,7 +1399,7 @@ const transformPropertySignature = (
|
|
|
1396
1399
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
1397
1400
|
node: tsm.PropertySignature,
|
|
1398
1401
|
readonlyModifier: 'add' | 'remove',
|
|
1399
|
-
readonlyContext:
|
|
1402
|
+
readonlyContext: StrictExtract<
|
|
1400
1403
|
ReadonlyContext,
|
|
1401
1404
|
Readonly<{
|
|
1402
1405
|
type: 'DeepReadonly' | 'none';
|
|
@@ -1406,8 +1409,8 @@ const transformPropertySignature = (
|
|
|
1406
1409
|
options: ReadonlyTransformerOptionsInternal,
|
|
1407
1410
|
): void => {
|
|
1408
1411
|
if (
|
|
1409
|
-
|
|
1410
|
-
|
|
1412
|
+
readonlyModifier === 'remove' ||
|
|
1413
|
+
readonlyContext.type === 'DeepReadonly'
|
|
1411
1414
|
) {
|
|
1412
1415
|
node.setIsReadonly(false);
|
|
1413
1416
|
} else {
|
|
@@ -1427,7 +1430,7 @@ const transformIndexSignatureDeclaration = (
|
|
|
1427
1430
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
1428
1431
|
node: tsm.IndexSignatureDeclaration,
|
|
1429
1432
|
readonlyModifier: 'add' | 'remove',
|
|
1430
|
-
readonlyContext:
|
|
1433
|
+
readonlyContext: StrictExtract<
|
|
1431
1434
|
ReadonlyContext,
|
|
1432
1435
|
Readonly<{
|
|
1433
1436
|
type: 'DeepReadonly' | 'none';
|
|
@@ -1443,8 +1446,8 @@ const transformIndexSignatureDeclaration = (
|
|
|
1443
1446
|
}
|
|
1444
1447
|
|
|
1445
1448
|
if (
|
|
1446
|
-
|
|
1447
|
-
|
|
1449
|
+
readonlyModifier === 'remove' ||
|
|
1450
|
+
readonlyContext.type === 'DeepReadonly'
|
|
1448
1451
|
) {
|
|
1449
1452
|
// node.setIsReadonly(false);
|
|
1450
1453
|
node.toggleModifier('readonly', false);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SafeUint, match } from 'ts-data-forge';
|
|
2
|
-
import { type SafeUintWithSmallInt } from 'ts-type-forge';
|
|
2
|
+
import { type SafeUintWithSmallInt, type StrictExtract } from 'ts-type-forge';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Controls whether to make a layer mutable during recursive transformation
|
|
@@ -37,7 +37,7 @@ export const nextReadonlyContext = <
|
|
|
37
37
|
indexedAccessDepthChange: 'decr' | 'incr' | 'keep' | 'infinity';
|
|
38
38
|
}
|
|
39
39
|
| {
|
|
40
|
-
nextReadonlyContextType:
|
|
40
|
+
nextReadonlyContextType: StrictExtract<
|
|
41
41
|
ReadonlyContext['type'],
|
|
42
42
|
'DeepReadonly'
|
|
43
43
|
>;
|
|
@@ -47,7 +47,7 @@ export const nextReadonlyContext = <
|
|
|
47
47
|
currentReadonlyContext: Curr;
|
|
48
48
|
}
|
|
49
49
|
>): Readonly<{
|
|
50
|
-
type:
|
|
50
|
+
type: Next | StrictExtract<ReadonlyContext['type'], 'DeepReadonly'>;
|
|
51
51
|
indexedAccessDepth: SafeUintWithSmallInt;
|
|
52
52
|
}> =>
|
|
53
53
|
curr.type === 'DeepReadonly'
|
|
@@ -58,7 +58,7 @@ const shouldSkipFile = (
|
|
|
58
58
|
|
|
59
59
|
const hasFileIgnoreComment = patterns.some((regex) => regex.test(code));
|
|
60
60
|
|
|
61
|
-
if (Arr.isEmpty(ignoredTransformers)
|
|
61
|
+
if (!hasFileIgnoreComment && Arr.isEmpty(ignoredTransformers)) {
|
|
62
62
|
return false;
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Arr, expectType } from 'ts-data-forge';
|
|
2
2
|
import * as tsm from 'ts-morph';
|
|
3
|
-
import { type DeepReadonly } from 'ts-type-forge';
|
|
3
|
+
import { type DeepReadonly, type StrictOmit } from 'ts-type-forge';
|
|
4
4
|
import { isAtomicTypeNode } from './is-atomic-type-node.mjs';
|
|
5
5
|
|
|
6
6
|
export const isShallowReadonlyTypeNode = (node: tsm.Node): boolean =>
|
|
@@ -17,7 +17,7 @@ export const isReadonlyTupleOrArrayTypeNode = (
|
|
|
17
17
|
node.getTypeNode().isKind(tsm.SyntaxKind.TupleType));
|
|
18
18
|
|
|
19
19
|
export type ReadonlyArrayTypeNode = tsm.TypeNode &
|
|
20
|
-
|
|
20
|
+
StrictOmit<tsm.TypeOperatorTypeNode, 'getOperator' | 'getTypeNode'> &
|
|
21
21
|
Readonly<{
|
|
22
22
|
getOperator: () => tsm.SyntaxKind.ReadonlyKeyword;
|
|
23
23
|
getTypeNode: () => tsm.ArrayTypeNode;
|
|
@@ -91,7 +91,7 @@ if (import.meta.vitest !== undefined) {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
export type ReadonlyTupleTypeNode = tsm.TypeNode &
|
|
94
|
-
|
|
94
|
+
StrictOmit<tsm.TypeOperatorTypeNode, 'getOperator' | 'getTypeNode'> &
|
|
95
95
|
Readonly<{
|
|
96
96
|
getOperator: () => tsm.SyntaxKind.ReadonlyKeyword;
|
|
97
97
|
getTypeNode: () => tsm.TupleTypeNode;
|
|
@@ -153,9 +153,9 @@ if (import.meta.vitest !== undefined) {
|
|
|
153
153
|
}
|
|
154
154
|
|
|
155
155
|
export type ReadonlyTypeReferenceNode = tsm.TypeNode &
|
|
156
|
-
|
|
156
|
+
StrictOmit<tsm.TypeReferenceNode, 'getTypeName' | 'getTypeArguments'> &
|
|
157
157
|
Readonly<{
|
|
158
|
-
getTypeName: () =>
|
|
158
|
+
getTypeName: () => StrictOmit<tsm.Identifier, 'getText'> &
|
|
159
159
|
Readonly<{
|
|
160
160
|
getText: () => 'Readonly';
|
|
161
161
|
}>;
|
|
@@ -23,10 +23,6 @@ export const shouldAvoidParenthesesForReadonly = (node: tsm.Node): boolean => {
|
|
|
23
23
|
// Check if parent is TypePredicate: x is T
|
|
24
24
|
// In this case, we MUST avoid parentheses: x is readonly T (not x is (readonly T))
|
|
25
25
|
// because `x is (readonly T)` is a syntax error
|
|
26
|
-
if (parent.isKind(tsm.SyntaxKind.TypePredicate)) {
|
|
27
|
-
return true;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
26
|
// For all other cases, keep parentheses for safety
|
|
31
|
-
return
|
|
27
|
+
return parent.isKind(tsm.SyntaxKind.TypePredicate);
|
|
32
28
|
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"append-as-const.d.mts","sourceRoot":"","sources":["../../src/cmd/append-as-const.mts"],"names":[],"mappings":""}
|