@@ -2,12 +2,10 @@ import fs from 'fs-extra';
22import path from 'node:path' ;
33import { applyTemplate , type TemplateConfiguration } from '../template' ;
44import sortObjectKeys from './sortObjectKeys' ;
5- import { SUPPORTED_REACT_NATIVE_VERSION } from '../constants' ;
65
76type Tool = {
87 name : string ;
98 description : string ;
10- package : Record < string , unknown > ;
119 condition ?: ( config : TemplateConfiguration ) => boolean ;
1210} ;
1311
@@ -21,109 +19,26 @@ type Options = {
2119const ESLINT = {
2220 name : 'ESLint with Prettier' ,
2321 description : 'Lint and format code' ,
24- package : {
25- scripts : {
26- lint : 'eslint "**/*.{js,ts,tsx}"' ,
27- } ,
28- prettier : {
29- quoteProps : 'consistent' ,
30- singleQuote : true ,
31- tabWidth : 2 ,
32- trailingComma : 'es5' ,
33- useTabs : false ,
34- } ,
35- devDependencies : {
36- '@eslint/compat' : '^1.3.2' ,
37- '@eslint/eslintrc' : '^3.3.1' ,
38- '@eslint/js' : '^9.35.0' ,
39- '@react-native/eslint-config' : SUPPORTED_REACT_NATIVE_VERSION ,
40- 'eslint-config-prettier' : '^10.1.8' ,
41- 'eslint-plugin-prettier' : '^5.5.4' ,
42- 'eslint' : '^9.35.0' ,
43- 'prettier' : '^2.8.8' ,
44- } ,
45- } ,
4622} ;
4723
4824const LEFTHOOK = {
4925 name : 'Lefthook with Commitlint' ,
5026 description : 'Manage Git hooks and lint commit messages' ,
51- package : {
52- commitlint : {
53- extends : [ '@commitlint/config-conventional' ] ,
54- } ,
55- devDependencies : {
56- '@commitlint/config-conventional' : '^19.8.1' ,
57- 'commitlint' : '^19.8.1' ,
58- 'lefthook' : '^2.0.3' ,
59- } ,
60- } ,
6127} ;
6228
6329const RELEASE_IT = {
6430 name : 'Release It' ,
6531 description : 'Automate versioning and package publishing tasks' ,
66- package : {
67- 'scripts' : {
68- release : 'release-it --only-version' ,
69- } ,
70- 'release-it' : {
71- git : {
72- // eslint-disable-next-line no-template-curly-in-string
73- commitMessage : 'chore: release ${version}' ,
74- // eslint-disable-next-line no-template-curly-in-string
75- tagName : 'v${version}' ,
76- } ,
77- npm : {
78- publish : true ,
79- } ,
80- github : {
81- release : true ,
82- } ,
83- plugins : {
84- '@release-it/conventional-changelog' : {
85- preset : {
86- name : 'angular' ,
87- } ,
88- } ,
89- } ,
90- } ,
91- 'devDependencies' : {
92- 'release-it' : '^19.0.4' ,
93- '@release-it/conventional-changelog' : '^10.0.1' ,
94- } ,
95- } ,
9632} ;
9733
9834const JEST = {
9935 name : 'Jest' ,
10036 description : 'Test JavaScript and TypeScript code' ,
101- package : {
102- scripts : {
103- test : 'jest' ,
104- } ,
105- jest : {
106- preset : 'react-native' ,
107- modulePathIgnorePatterns : [
108- '<rootDir>/example/node_modules' ,
109- '<rootDir>/lib/' ,
110- ] ,
111- } ,
112- devDependencies : {
113- '@types/jest' : '^29.5.14' ,
114- 'jest' : '^29.7.0' ,
115- } ,
116- } ,
11737} ;
11838
11939const TURBOREPO = {
12040 name : 'Turborepo' ,
12141 description : 'Cache build outputs on CI' ,
122- package : {
123- devDependencies : {
124- turbo : '^2.5.6' ,
125- } ,
126- } ,
12742} ;
12843
12944export const AVAILABLE_TOOLS = {
@@ -168,39 +83,49 @@ export async function configureTools({
16883 continue ;
16984 }
17085
171- const files = path . resolve ( __dirname , `../../templates/tools/${ key } ` ) ;
86+ const toolDir = path . resolve ( __dirname , `../../templates/tools/${ key } ` ) ;
17287
173- if ( fs . existsSync ( files ) ) {
174- await applyTemplate ( config , files , root ) ;
88+ if ( fs . existsSync ( toolDir ) ) {
89+ await applyTemplate ( config , toolDir , root ) ;
17590 }
17691
177- for ( const [ key , value ] of Object . entries ( tool . package ) ) {
178- if (
179- typeof value === 'object' &&
180- value !== null &&
181- ! Array . isArray ( value )
182- ) {
183- if ( typeof packageJson [ key ] === 'object' || packageJson [ key ] == null ) {
184- packageJson [ key ] = {
185- ...packageJson [ key ] ,
186- ...value ,
187- } ;
92+ const pkgPath = path . join ( toolDir , '~package.json' ) ;
18893
94+ if ( fs . existsSync ( pkgPath ) ) {
95+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
96+ const toolPkg = ( await fs . readJson ( pkgPath ) ) as Record < string , unknown > ;
97+
98+ for ( const [ field , value ] of Object . entries ( toolPkg ) ) {
99+ if (
100+ typeof value === 'object' &&
101+ value !== null &&
102+ ! Array . isArray ( value )
103+ ) {
189104 if (
190- key === 'dependencies' ||
191- key === 'devDependencies' ||
192- key === 'peerDependencies'
105+ typeof packageJson [ field ] === 'object' ||
106+ packageJson [ field ] == null
193107 ) {
194- // @ts -expect-error: We know they are objects here
195- packageJson [ key ] = sortObjectKeys ( packageJson [ key ] ) ;
108+ packageJson [ field ] = {
109+ ...packageJson [ field ] ,
110+ ...value ,
111+ } ;
112+
113+ if (
114+ field === 'dependencies' ||
115+ field === 'devDependencies' ||
116+ field === 'peerDependencies'
117+ ) {
118+ // @ts -expect-error: We know they are objects here
119+ packageJson [ field ] = sortObjectKeys ( packageJson [ field ] ) ;
120+ }
121+ } else {
122+ throw new Error (
123+ `Cannot merge '${ field } ' field because it is not an object (got '${ String ( packageJson [ field ] ) } ').`
124+ ) ;
196125 }
197126 } else {
198- throw new Error (
199- `Cannot merge '${ key } ' field because it is not an object (got '${ String ( packageJson [ key ] ) } ').`
200- ) ;
127+ packageJson [ field ] = value ;
201128 }
202- } else {
203- packageJson [ key ] = value ;
204129 }
205130 }
206131 }
0 commit comments