1- const { relative, dirname, join, extname, posix , win32 } = require ( 'path' )
2- const { defaults, pick, omit, uniq, isPlainObject } = require ( 'lodash' )
1+ const { relative, dirname, join, extname } = require ( 'path' )
2+ const { defaults, defaultsDeep , pick, omit, uniq, isPlainObject } = require ( 'lodash' )
33const ciVersions = require ( './util/ci-versions.js' )
44const parseDependabot = require ( './util/dependabot.js' )
55const git = require ( './util/git.js' )
66const gitignore = require ( './util/gitignore.js' )
77const { mergeWithCustomizers, customizers } = require ( './util/merge.js' )
88const { FILE_KEYS , parseConfig : parseFiles , getAddedFiles, mergeFiles } = require ( './util/files.js' )
9+ const template = require ( './util/template.js' )
10+ const getCmdPath = require ( './util/get-cmd-path.js' )
11+ const importOrRequire = require ( './util/import-or-require.js' )
12+ const { makePosix, deglob, posixDir, posixGlob } = require ( './util/path.js' )
13+ const { name : NAME , version : LATEST_VERSION } = require ( '../package.json' )
914
1015const CONFIG_KEY = 'templateOSS'
11- const getPkgConfig = ( pkg ) => pkg [ CONFIG_KEY ] || { }
12-
13- const { name : NAME , version : LATEST_VERSION } = require ( '../package.json' )
1416const MERGE_KEYS = [ ...FILE_KEYS , 'defaultContent' , 'content' ]
1517const DEFAULT_CONTENT = require . resolve ( NAME )
18+ const getPkgConfig = ( pkg ) => pkg [ CONFIG_KEY ] || { }
1619
1720const merge = mergeWithCustomizers (
1821 customizers . mergeArrays ( 'branches' , 'distPaths' , 'allowPaths' , 'ignorePaths' ) ,
@@ -23,43 +26,6 @@ const merge = mergeWithCustomizers(
2326 }
2427)
2528
26- const makePosix = ( v ) => v . split ( win32 . sep ) . join ( posix . sep )
27- const deglob = ( v ) => makePosix ( v ) . replace ( / [ / * ] + $ / , '' )
28- const posixDir = ( v ) => `${ v === '.' ? '' : deglob ( v ) . replace ( / \/ $ / , '' ) } ${ posix . sep } `
29- const posixGlob = ( str ) => `${ posixDir ( str ) } **`
30-
31- const getCmdPath = ( key , { pkgConfig, rootConfig, isRoot, pkg, rootPkg } ) => {
32- const result = ( local , isRelative ) => {
33- let root = local
34- const isLocal = local . startsWith ( '.' ) || local . startsWith ( '/' )
35-
36- if ( isLocal ) {
37- if ( isRelative ) {
38- // Make a path relative from a workspace to the root if we are in a workspace
39- local = makePosix ( join ( relative ( pkg . path , rootPkg . path ) , local ) )
40- }
41- local = `node ${ local } `
42- root = `node ${ root } `
43- }
44-
45- return {
46- isLocal,
47- local,
48- root,
49- }
50- }
51-
52- if ( pkgConfig [ key ] ) {
53- return result ( pkgConfig [ key ] )
54- }
55-
56- if ( rootConfig [ key ] ) {
57- return result ( rootConfig [ key ] , ! isRoot )
58- }
59-
60- return result ( key )
61- }
62-
6329const mergeConfigs = ( ...configs ) => {
6430 const mergedConfig = merge ( ...configs . map ( c => pick ( c , MERGE_KEYS ) ) )
6531 return defaults ( mergedConfig , {
@@ -72,37 +38,33 @@ const mergeConfigs = (...configs) => {
7238 } )
7339}
7440
75- const readContentPath = ( path ) => {
41+ const readContentPath = async ( path ) => {
7642 if ( ! path ) {
7743 return { }
7844 }
7945
80- let content = { }
8146 const index = extname ( path ) === '.js' ? path : join ( path , 'index.js' )
8247 const dir = dirname ( index )
83-
84- try {
85- content = require ( index )
86- } catch {
87- // its ok if this fails since the content dir
88- // might only be to provide other files. the
89- // index.js is optional
90- }
48+ const content = await importOrRequire ( index )
9149
9250 return { content, dir }
9351}
9452
95- const getConfig = ( path , rawConfig ) => {
96- const config = omit ( readContentPath ( path ) . content , FILE_KEYS )
53+ const getConfig = async ( path , rawConfig ) => {
54+ const { content } = await readContentPath ( path )
55+ const config = omit ( content , FILE_KEYS )
9756 return merge ( config , rawConfig ? omit ( rawConfig , FILE_KEYS ) : { } )
9857}
9958
100- const getFiles = ( path , rawConfig ) => {
101- const { content, dir } = readContentPath ( path )
59+ const getFiles = async ( path , rawConfig , templateSettings ) => {
60+ const { content, dir } = await readContentPath ( path )
10261 if ( ! dir ) {
10362 return [ ]
10463 }
105- return [ parseFiles ( pick ( content , FILE_KEYS ) , dir , pick ( rawConfig , FILE_KEYS ) ) , dir ]
64+ return [
65+ parseFiles ( pick ( content , FILE_KEYS ) , dir , pick ( rawConfig , FILE_KEYS ) , templateSettings ) ,
66+ dir ,
67+ ]
10668}
10769
10870const getFullConfig = async ( {
@@ -127,39 +89,15 @@ const getFullConfig = async ({
12789 // These config items are merged betweent the root and child workspaces and only come from
12890 // the package.json because they can be used to read configs from other the content directories
12991 const mergedConfig = mergeConfigs ( rootPkg . config , pkg . config )
130-
131- const defaultConfig = getConfig ( DEFAULT_CONTENT )
132- const [ defaultFiles , defaultDir ] = getFiles ( DEFAULT_CONTENT , mergedConfig )
92+ const defaultConfig = await getConfig ( DEFAULT_CONTENT )
13393 const useDefault = mergedConfig . defaultContent && defaultConfig
13494
135- const rootConfig = getConfig ( rootPkg . config . content , rootPkg . config )
136- const [ rootFiles , rootDir ] = getFiles ( rootPkg . config . content , mergedConfig )
95+ const rootConfig = await getConfig ( rootPkg . config . content , rootPkg . config )
13796
13897 // The content config only gets set from the package we are in, it doesn't inherit
13998 // anything from the root
14099 const rootPkgConfig = merge ( useDefault , rootConfig )
141- const pkgConfig = merge ( useDefault , getConfig ( pkg . config . content , pkg . config ) )
142- const [ pkgFiles , pkgDir ] = getFiles ( mergedConfig . content , mergedConfig )
143-
144- // Files get merged in from the default content (that template-oss provides) as well
145- // as any content paths provided from the root or the workspace
146- const fileDirs = uniq ( [ useDefault && defaultDir , rootDir , pkgDir ] . filter ( Boolean ) )
147- const files = mergeFiles ( useDefault && defaultFiles , rootFiles , pkgFiles )
148- const repoFiles = isRoot ? files . rootRepo : files . workspaceRepo
149- const moduleFiles = isRoot ? files . rootModule : files . workspaceModule
150-
151- const allowRootDirs = [
152- // Allways allow module files in root or workspaces
153- ...getAddedFiles ( moduleFiles ) ,
154- ...isRoot ? [
155- // in the root allow all repo files
156- ...getAddedFiles ( repoFiles ) ,
157- // and allow all workspace repo level files in the root
158- ...pkgs
159- . filter ( p => p . path !== rootPkg . path && p . config . workspaceRepo !== false )
160- . flatMap ( ( ) => getAddedFiles ( files . workspaceRepo ) ) ,
161- ] : [ ] ,
162- ]
100+ const pkgConfig = merge ( useDefault , await getConfig ( pkg . config . content , pkg . config ) )
163101
164102 const npmPath = getCmdPath ( 'npm' , { pkgConfig, rootConfig, isRoot, pkg, rootPkg } )
165103 const npxPath = getCmdPath ( 'npx' , { pkgConfig, rootConfig, isRoot, pkg, rootPkg } )
@@ -185,6 +123,8 @@ const getFullConfig = async ({
185123 ? pkgConfig . releaseBranch . replace ( / \* / g, pkgConfig . backport )
186124 : defaultBranch
187125
126+ const esm = pkg . pkgJson ?. type === 'module' || ! ! pkgConfig . typescript || ! ! pkgConfig . esm
127+
188128 // all derived keys
189129 const derived = {
190130 isRoot,
@@ -209,25 +149,22 @@ const getFullConfig = async ({
209149 releaseBranch,
210150 publishTag,
211151 dependabot : parseDependabot ( pkgConfig , defaultConfig , gitBranches . branches ) ,
212- // repo
152+ // paths
213153 repoDir : rootPkg . path ,
214- repoFiles,
215- applyRepo : ! ! repoFiles ,
216- // module
217154 moduleDir : pkg . path ,
218- moduleFiles,
219- applyModule : ! ! moduleFiles ,
220- // package
221155 pkgName : pkg . pkgJson . name ,
222156 pkgNameFs : pkg . pkgJson . name . replace ( / \/ / g, '-' ) . replace ( / @ / g, '' ) ,
223- // paths
224157 pkgPath,
225158 pkgDir : posixDir ( pkgPath ) ,
226159 pkgGlob : posixGlob ( pkgPath ) ,
227160 pkgFlags : isWorkspace ? `-w ${ pkg . pkgJson . name } ` : '' ,
228161 allFlags : isMono ? '-ws -iwr --if-present' : '' ,
229162 workspacePaths,
230163 workspaceGlobs : workspacePaths . map ( posixGlob ) ,
164+ // type
165+ esm,
166+ cjsExt : esm ? 'cjs' : 'js' ,
167+ deleteJsExt : esm ? 'js' : 'cjs' ,
231168 // booleans to control application of updates
232169 isForce,
233170 isDogFood,
@@ -243,36 +180,29 @@ const getFullConfig = async ({
243180 lockfile : rootPkgConfig . lockfile ,
244181 // ci versions / engines
245182 ciVersions : ciVersions . get ( pkg . pkgJson . engines ?. node , pkgConfig ) ,
246- // gitignore
247- ignorePaths : [
248- ...gitignore . sort ( [
249- ...gitignore . allowRootDir ( allowRootDirs ) ,
250- ...isRoot && pkgConfig . lockfile ? [ '!/package-lock.json' ] : [ ] ,
251- ...( pkgConfig . allowPaths || [ ] ) . map ( ( p ) => `!${ p } ` ) ,
252- ...( pkgConfig . ignorePaths || [ ] ) ,
253- ] ) ,
254- // these cant be sorted since they rely on order
255- // to allow a previously ignored directoy
256- ...isRoot
257- ? gitignore . allowDir ( wsPkgs . map ( ( p ) => makePosix ( relative ( rootPkg . path , p . path ) ) ) )
258- : [ ] ,
259- ] ,
260183 // needs update if we are dogfooding this repo, with force argv, or its
261184 // behind the current version
262185 needsUpdate : isForce || isDogFood || ! isLatest ,
263186 // templateoss specific values
264187 __NAME__ : NAME ,
265188 __CONFIG_KEY__ : CONFIG_KEY ,
266189 __VERSION__ : LATEST_VERSION ,
267- __PARTIAL_DIRS__ : fileDirs ,
268190 }
269191
270- if ( ! pkgConfig . eslint ) {
271- derived . ignorePaths = derived . ignorePaths . filter ( p => ! p . includes ( 'eslint' ) )
272- if ( Array . isArray ( pkgConfig . requiredPackages ?. devDependencies ) ) {
273- pkgConfig . requiredPackages . devDependencies =
274- pkgConfig . requiredPackages . devDependencies . filter ( p => ! p . includes ( 'eslint' ) )
275- }
192+ if ( ! pkgConfig . eslint && Array . isArray ( pkgConfig . requiredPackages ?. devDependencies ) ) {
193+ pkgConfig . requiredPackages . devDependencies =
194+ pkgConfig . requiredPackages . devDependencies . filter ( p => ! p . includes ( 'eslint' ) )
195+ }
196+
197+ if ( pkgConfig . typescript ) {
198+ defaultsDeep ( pkgConfig , { allowPaths : [ ] , requiredPackages : { devDependencies : [ ] } } )
199+ pkgConfig . distPaths = null
200+ pkgConfig . allowPaths . push ( '/src/' )
201+ pkgConfig . requiredPackages . devDependencies . push (
202+ 'typescript' ,
203+ 'tshy' ,
204+ '@typescript-eslint/parser'
205+ )
276206 }
277207
278208 const gitUrl = await git . getUrl ( rootPkg . path )
@@ -284,10 +214,55 @@ const getFullConfig = async ({
284214 }
285215 }
286216
287- return {
288- ...pkgConfig ,
289- ...derived ,
290- }
217+ const fullConfig = { ...pkgConfig , ...derived }
218+
219+ // files, come at the end since file names can be based on config
220+ const [ defaultFiles , defaultDir ] = await getFiles ( DEFAULT_CONTENT , mergedConfig , fullConfig )
221+ const [ rootFiles , rootDir ] = await getFiles ( rootPkg . config . content , mergedConfig , fullConfig )
222+ const [ pkgFiles , pkgDir ] = await getFiles ( mergedConfig . content , mergedConfig , fullConfig )
223+
224+ // Files get merged in from the default content (that template-oss provides) as well
225+ // as any content paths provided from the root or the workspace
226+ const fileDirs = uniq ( [ useDefault && defaultDir , rootDir , pkgDir ] . filter ( Boolean ) )
227+ const files = mergeFiles ( useDefault && defaultFiles , rootFiles , pkgFiles )
228+ const repoFiles = isRoot ? files . rootRepo : files . workspaceRepo
229+ const moduleFiles = isRoot ? files . rootModule : files . workspaceModule
230+
231+ Object . assign ( fullConfig , {
232+ repoFiles,
233+ moduleFiles,
234+ applyRepo : ! ! repoFiles ,
235+ applyModule : ! ! moduleFiles ,
236+ __PARTIAL_DIRS__ : fileDirs ,
237+ // gitignore, these use the full config so need to come at the very end
238+ ignorePaths : [
239+ ...gitignore . sort ( [
240+ ...gitignore . allowRootDir ( [
241+ // Allways allow module files in root or workspaces
242+ ...getAddedFiles ( moduleFiles ) . map ( s => template ( s , fullConfig ) ) ,
243+ ...isRoot ? [
244+ // in the root allow all repo files
245+ ...getAddedFiles ( repoFiles ) . map ( s => template ( s , fullConfig ) ) ,
246+ // and allow all workspace repo level files in the root
247+ ...pkgs
248+ . filter ( p => p . path !== rootPkg . path && p . config . workspaceRepo !== false )
249+ . flatMap ( ( ) => getAddedFiles ( files . workspaceRepo ) ) ,
250+ ] : [ ] ,
251+ ] ) ,
252+ ...isRoot && pkgConfig . lockfile ? [ '!/package-lock.json' ] : [ ] ,
253+ ...( pkgConfig . allowPaths || [ ] ) . map ( ( p ) => `!${ p } ` ) ,
254+ ...( pkgConfig . distPaths || [ ] ) . map ( ( p ) => `!/${ p } ` ) ,
255+ ...( pkgConfig . ignorePaths || [ ] ) ,
256+ ] ) ,
257+ // these cant be sorted since they rely on order
258+ // to allow a previously ignored directoy
259+ ...isRoot
260+ ? gitignore . allowDir ( wsPkgs . map ( ( p ) => makePosix ( relative ( rootPkg . path , p . path ) ) ) )
261+ : [ ] ,
262+ ] . filter ( p => ! pkgConfig . eslint ? ! p . includes ( 'eslint' ) : true ) ,
263+ } )
264+
265+ return fullConfig
291266}
292267
293268module . exports = getFullConfig
0 commit comments