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' )
3
3
const ciVersions = require ( './util/ci-versions.js' )
4
4
const parseDependabot = require ( './util/dependabot.js' )
5
5
const git = require ( './util/git.js' )
6
6
const gitignore = require ( './util/gitignore.js' )
7
7
const { mergeWithCustomizers, customizers } = require ( './util/merge.js' )
8
8
const { 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' )
9
14
10
15
const CONFIG_KEY = 'templateOSS'
11
- const getPkgConfig = ( pkg ) => pkg [ CONFIG_KEY ] || { }
12
-
13
- const { name : NAME , version : LATEST_VERSION } = require ( '../package.json' )
14
16
const MERGE_KEYS = [ ...FILE_KEYS , 'defaultContent' , 'content' ]
15
17
const DEFAULT_CONTENT = require . resolve ( NAME )
18
+ const getPkgConfig = ( pkg ) => pkg [ CONFIG_KEY ] || { }
16
19
17
20
const merge = mergeWithCustomizers (
18
21
customizers . mergeArrays ( 'branches' , 'distPaths' , 'allowPaths' , 'ignorePaths' ) ,
@@ -23,43 +26,6 @@ const merge = mergeWithCustomizers(
23
26
}
24
27
)
25
28
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
-
63
29
const mergeConfigs = ( ...configs ) => {
64
30
const mergedConfig = merge ( ...configs . map ( c => pick ( c , MERGE_KEYS ) ) )
65
31
return defaults ( mergedConfig , {
@@ -72,37 +38,33 @@ const mergeConfigs = (...configs) => {
72
38
} )
73
39
}
74
40
75
- const readContentPath = ( path ) => {
41
+ const readContentPath = async ( path ) => {
76
42
if ( ! path ) {
77
43
return { }
78
44
}
79
45
80
- let content = { }
81
46
const index = extname ( path ) === '.js' ? path : join ( path , 'index.js' )
82
47
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 )
91
49
92
50
return { content, dir }
93
51
}
94
52
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 )
97
56
return merge ( config , rawConfig ? omit ( rawConfig , FILE_KEYS ) : { } )
98
57
}
99
58
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 )
102
61
if ( ! dir ) {
103
62
return [ ]
104
63
}
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
+ ]
106
68
}
107
69
108
70
const getFullConfig = async ( {
@@ -127,39 +89,15 @@ const getFullConfig = async ({
127
89
// These config items are merged betweent the root and child workspaces and only come from
128
90
// the package.json because they can be used to read configs from other the content directories
129
91
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 )
133
93
const useDefault = mergedConfig . defaultContent && defaultConfig
134
94
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 )
137
96
138
97
// The content config only gets set from the package we are in, it doesn't inherit
139
98
// anything from the root
140
99
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 ) )
163
101
164
102
const npmPath = getCmdPath ( 'npm' , { pkgConfig, rootConfig, isRoot, pkg, rootPkg } )
165
103
const npxPath = getCmdPath ( 'npx' , { pkgConfig, rootConfig, isRoot, pkg, rootPkg } )
@@ -185,6 +123,8 @@ const getFullConfig = async ({
185
123
? pkgConfig . releaseBranch . replace ( / \* / g, pkgConfig . backport )
186
124
: defaultBranch
187
125
126
+ const esm = pkg . pkgJson ?. type === 'module' || ! ! pkgConfig . typescript || ! ! pkgConfig . esm
127
+
188
128
// all derived keys
189
129
const derived = {
190
130
isRoot,
@@ -209,25 +149,22 @@ const getFullConfig = async ({
209
149
releaseBranch,
210
150
publishTag,
211
151
dependabot : parseDependabot ( pkgConfig , defaultConfig , gitBranches . branches ) ,
212
- // repo
152
+ // paths
213
153
repoDir : rootPkg . path ,
214
- repoFiles,
215
- applyRepo : ! ! repoFiles ,
216
- // module
217
154
moduleDir : pkg . path ,
218
- moduleFiles,
219
- applyModule : ! ! moduleFiles ,
220
- // package
221
155
pkgName : pkg . pkgJson . name ,
222
156
pkgNameFs : pkg . pkgJson . name . replace ( / \/ / g, '-' ) . replace ( / @ / g, '' ) ,
223
- // paths
224
157
pkgPath,
225
158
pkgDir : posixDir ( pkgPath ) ,
226
159
pkgGlob : posixGlob ( pkgPath ) ,
227
160
pkgFlags : isWorkspace ? `-w ${ pkg . pkgJson . name } ` : '' ,
228
161
allFlags : isMono ? '-ws -iwr --if-present' : '' ,
229
162
workspacePaths,
230
163
workspaceGlobs : workspacePaths . map ( posixGlob ) ,
164
+ // type
165
+ esm,
166
+ cjsExt : esm ? 'cjs' : 'js' ,
167
+ deleteJsExt : esm ? 'js' : 'cjs' ,
231
168
// booleans to control application of updates
232
169
isForce,
233
170
isDogFood,
@@ -243,36 +180,29 @@ const getFullConfig = async ({
243
180
lockfile : rootPkgConfig . lockfile ,
244
181
// ci versions / engines
245
182
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
- ] ,
260
183
// needs update if we are dogfooding this repo, with force argv, or its
261
184
// behind the current version
262
185
needsUpdate : isForce || isDogFood || ! isLatest ,
263
186
// templateoss specific values
264
187
__NAME__ : NAME ,
265
188
__CONFIG_KEY__ : CONFIG_KEY ,
266
189
__VERSION__ : LATEST_VERSION ,
267
- __PARTIAL_DIRS__ : fileDirs ,
268
190
}
269
191
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
+ )
276
206
}
277
207
278
208
const gitUrl = await git . getUrl ( rootPkg . path )
@@ -284,10 +214,55 @@ const getFullConfig = async ({
284
214
}
285
215
}
286
216
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
291
266
}
292
267
293
268
module . exports = getFullConfig
0 commit comments