@npmcli/template-oss 4.1.1 → 4.2.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/bin/release-please.js +7 -0
- package/lib/apply/apply-files.js +1 -1
- package/lib/apply/index.js +1 -1
- package/lib/check/check-apply.js +5 -4
- package/lib/check/index.js +1 -1
- package/lib/config.js +150 -111
- package/lib/content/_setup-ci-on.yml +32 -0
- package/lib/content/_setup-deps.yml +1 -0
- package/lib/content/{setup-git.yml → _setup-git.yml} +2 -2
- package/lib/content/_setup-job-matrix.yml +27 -0
- package/lib/content/_setup-job.yml +6 -0
- package/lib/content/{setup-node.yml → _setup-node.yml} +2 -0
- package/lib/content/audit.yml +2 -6
- package/lib/content/ci.yml +5 -51
- package/lib/content/dependabot.yml +18 -0
- package/lib/content/eslintrc.js +7 -0
- package/lib/content/gitignore +0 -13
- package/lib/content/index.js +36 -14
- package/lib/content/pkg.json +21 -3
- package/lib/content/post-dependabot.yml +3 -8
- package/lib/content/pull-request.yml +2 -6
- package/lib/content/release-please.yml +6 -15
- package/lib/content/release.yml +20 -0
- package/lib/index.js +21 -21
- package/lib/release-please/github.js +27 -23
- package/lib/release-please/node-workspace.js +8 -2
- package/lib/util/files.js +69 -27
- package/lib/util/gitignore.js +34 -0
- package/lib/util/merge.js +21 -0
- package/lib/util/parser.js +3 -2
- package/lib/util/template.js +21 -19
- package/package.json +8 -2
- package/lib/content/release-test.yml +0 -46
- package/lib/content/setup-deps.yml +0 -1
package/lib/content/index.js
CHANGED
|
@@ -5,9 +5,9 @@ const releasePlease = () => ({
|
|
|
5
5
|
file: 'release-please.yml',
|
|
6
6
|
filter: (o) => !o.pkg.private,
|
|
7
7
|
},
|
|
8
|
-
'.github/workflows/release
|
|
9
|
-
file: 'release
|
|
10
|
-
filter: (o) => !o.pkg.private
|
|
8
|
+
'.github/workflows/release.yml': {
|
|
9
|
+
file: 'release.yml',
|
|
10
|
+
filter: (o) => !o.pkg.private,
|
|
11
11
|
},
|
|
12
12
|
'.release-please-manifest.json': {
|
|
13
13
|
file: 'release-please-manifest.json',
|
|
@@ -25,22 +25,29 @@ const releasePlease = () => ({
|
|
|
25
25
|
},
|
|
26
26
|
})
|
|
27
27
|
|
|
28
|
+
const tap = (name) => ({
|
|
29
|
+
'.github/matchers/tap.json': 'tap.json',
|
|
30
|
+
[`.github/workflows/ci${name ? `-${name}` : ''}.yml`]: 'ci.yml',
|
|
31
|
+
})
|
|
32
|
+
|
|
28
33
|
// Changes applied to the root of the repo
|
|
29
34
|
const rootRepo = {
|
|
30
35
|
add: {
|
|
31
36
|
'.commitlintrc.js': 'commitlintrc.js',
|
|
32
|
-
'.github/workflows/ci.yml': 'ci.yml',
|
|
33
37
|
'.github/ISSUE_TEMPLATE/bug.yml': 'bug.yml',
|
|
34
38
|
'.github/ISSUE_TEMPLATE/config.yml': 'config.yml',
|
|
35
39
|
'.github/CODEOWNERS': 'CODEOWNERS',
|
|
36
40
|
'.github/dependabot.yml': 'dependabot.yml',
|
|
37
|
-
'.github/matchers/tap.json': 'tap.json',
|
|
38
41
|
'.github/workflows/audit.yml': 'audit.yml',
|
|
39
42
|
'.github/workflows/codeql-analysis.yml': 'codeql-analysis.yml',
|
|
40
43
|
'.github/workflows/post-dependabot.yml': 'post-dependabot.yml',
|
|
41
44
|
'.github/workflows/pull-request.yml': 'pull-request.yml',
|
|
42
45
|
...releasePlease(),
|
|
46
|
+
...tap(),
|
|
43
47
|
},
|
|
48
|
+
rm: [
|
|
49
|
+
'.github/workflows/release-test.yml',
|
|
50
|
+
],
|
|
44
51
|
}
|
|
45
52
|
|
|
46
53
|
// These are also applied to the root of the repo
|
|
@@ -65,9 +72,8 @@ const rootModule = {
|
|
|
65
72
|
// Changes for each workspace but applied to the root of the repo
|
|
66
73
|
const workspaceRepo = {
|
|
67
74
|
add: {
|
|
68
|
-
...releasePlease(
|
|
69
|
-
|
|
70
|
-
'.github/workflows/ci-{{pkgNameFs}}.yml': 'ci.yml',
|
|
75
|
+
...releasePlease(),
|
|
76
|
+
...tap('{{pkgNameFs}}'),
|
|
71
77
|
},
|
|
72
78
|
rm: [
|
|
73
79
|
// These are the old release please files that should be removed now
|
|
@@ -95,17 +101,33 @@ module.exports = {
|
|
|
95
101
|
workspaceRepo,
|
|
96
102
|
workspaceModule,
|
|
97
103
|
windowsCI: true,
|
|
104
|
+
macCI: true,
|
|
98
105
|
branches: ['main', 'latest'],
|
|
99
106
|
releaseBranches: [],
|
|
100
107
|
defaultBranch: 'main',
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
108
|
+
distPaths: [
|
|
109
|
+
'bin/',
|
|
110
|
+
'lib/',
|
|
111
|
+
],
|
|
112
|
+
allowPaths: [
|
|
113
|
+
'/bin/',
|
|
114
|
+
'/lib/',
|
|
115
|
+
'/.eslintrc.local.*',
|
|
116
|
+
'**/.gitignore',
|
|
117
|
+
'/docs/',
|
|
118
|
+
'/tap-snapshots/',
|
|
119
|
+
'/test/',
|
|
120
|
+
'/map.js',
|
|
121
|
+
'/scripts/',
|
|
122
|
+
'/README*',
|
|
123
|
+
'/LICENSE*',
|
|
124
|
+
'/CHANGELOG*',
|
|
125
|
+
],
|
|
126
|
+
ignorePaths: [],
|
|
106
127
|
ciVersions: ['14.17.0', '14.x', '16.13.0', '16.x', '18.0.0', '18.x'],
|
|
107
128
|
lockfile: false,
|
|
108
|
-
|
|
129
|
+
npm: 'npm',
|
|
130
|
+
npx: 'npx',
|
|
109
131
|
unwantedPackages: [
|
|
110
132
|
'eslint',
|
|
111
133
|
'eslint-plugin-node',
|
package/lib/content/pkg.json
CHANGED
|
@@ -5,23 +5,41 @@
|
|
|
5
5
|
"lint": "eslint \"**/*.js\"",
|
|
6
6
|
"postlint": "template-oss-check",
|
|
7
7
|
"template-oss-apply": "template-oss-apply --force",
|
|
8
|
-
"lintfix": "{{
|
|
8
|
+
"lintfix": "{{localNpmPath}} run lint -- --fix",
|
|
9
9
|
"preversion": {{{del}}},
|
|
10
10
|
"postversion": {{{del}}},
|
|
11
11
|
"prepublishOnly": {{{del}}},
|
|
12
|
+
"postpublish": {{{del}}},
|
|
12
13
|
"snap": "tap",
|
|
13
14
|
"test": "tap",
|
|
14
|
-
"posttest": "{{
|
|
15
|
+
"posttest": "{{localNpmPath}} run lint",
|
|
16
|
+
{{#if isRootMono}}
|
|
17
|
+
"test-all": "{{localNpmPath}} run test -ws -iwr --if-present",
|
|
18
|
+
"lint-all": "{{localNpmPath}} run lint -ws -iwr --if-present",
|
|
19
|
+
{{/if}}
|
|
15
20
|
"template-copy": {{{del}}},
|
|
16
21
|
"lint:fix": {{{del}}}
|
|
17
22
|
},
|
|
18
23
|
"repository": {{#if repository}}{{{json repository}}}{{else}}{{{del}}}{{/if}},
|
|
19
24
|
"engines": {
|
|
25
|
+
{{#if engines}}
|
|
20
26
|
"node": {{{json engines}}}
|
|
27
|
+
{{/if}}
|
|
21
28
|
},
|
|
22
29
|
{{{json __CONFIG_KEY__}}}: {
|
|
23
30
|
"version": {{#if isDogFood}}{{{del}}}{{else}}{{{json __VERSION__}}}{{/if}}
|
|
24
31
|
},
|
|
25
32
|
"templateVersion": {{{del}}},
|
|
26
|
-
"standard": {{{del}}}
|
|
33
|
+
"standard": {{{del}}},
|
|
34
|
+
"tap": {
|
|
35
|
+
{{#if isRootMono}}
|
|
36
|
+
"test-ignore": "^({{#each workspaceGlobs}}{{this}}{{#unless @last}}|{{/unless}}{{/each}})/",
|
|
37
|
+
{{/if}}
|
|
38
|
+
"nyc-arg": [
|
|
39
|
+
{{#if isRootMono}}
|
|
40
|
+
{{#each workspaceGlobs}}"--exclude", "{{this}}/**",{{/each}}
|
|
41
|
+
{{/if}}
|
|
42
|
+
"--exclude", "tap-snapshots/**"
|
|
43
|
+
]
|
|
44
|
+
}
|
|
27
45
|
}
|
|
@@ -9,12 +9,7 @@ permissions:
|
|
|
9
9
|
|
|
10
10
|
jobs:
|
|
11
11
|
template-oss-apply:
|
|
12
|
-
|
|
13
|
-
if: github.actor == 'dependabot[bot]'
|
|
14
|
-
steps:
|
|
15
|
-
{{> setupGit with=(obj ref="${{ github.event.pull_request.head_ref }}")}}
|
|
16
|
-
{{> setupNode}}
|
|
17
|
-
{{> setupDeps}}
|
|
12
|
+
{{> setupJob jobIf="github.actor == 'dependabot[bot]'" checkout=(obj ref="${{ github.event.pull_request.head_ref }}")}}
|
|
18
13
|
- name: Dependabot metadata
|
|
19
14
|
id: metadata
|
|
20
15
|
uses: dependabot/fetch-metadata@v1.1.1
|
|
@@ -25,7 +20,7 @@ jobs:
|
|
|
25
20
|
env:
|
|
26
21
|
GITHUB_TOKEN: $\{{ secrets.GITHUB_TOKEN }}
|
|
27
22
|
run: |
|
|
28
|
-
|
|
23
|
+
{{rootNpmPath}} run template-oss-apply
|
|
29
24
|
git commit -am "chore: postinstall for dependabot template-oss PR"
|
|
30
25
|
git push
|
|
31
|
-
|
|
26
|
+
{{rootNpmPath}} run lint
|
|
@@ -11,14 +11,10 @@ on:
|
|
|
11
11
|
jobs:
|
|
12
12
|
check:
|
|
13
13
|
name: Check PR Title or Commits
|
|
14
|
-
|
|
15
|
-
steps:
|
|
16
|
-
{{> setupGit with=(obj fetch-depth=0)}}
|
|
17
|
-
{{> setupNode}}
|
|
18
|
-
{{> setupDeps}}
|
|
14
|
+
{{> setupJob checkout=(obj fetch-depth=0)}}
|
|
19
15
|
- name: Check commits or PR title
|
|
20
16
|
env:
|
|
21
17
|
PR_TITLE: $\{{ github.event.pull_request.title }}
|
|
22
18
|
run: |
|
|
23
|
-
|
|
19
|
+
{{rootNpxPath}} --offline commitlint -V --from origin/{{defaultBranch}} --to $\{{ github.event.pull_request.head.sha }} \
|
|
24
20
|
|| echo $PR_TITLE | npx --offline commitlint -V
|
|
@@ -16,14 +16,10 @@ permissions:
|
|
|
16
16
|
|
|
17
17
|
jobs:
|
|
18
18
|
release-please:
|
|
19
|
-
runs-on: ubuntu-latest
|
|
20
19
|
outputs:
|
|
21
20
|
pr: $\{{ steps.release.outputs.pr }}
|
|
22
21
|
release: $\{{ steps.release.outputs.release }}
|
|
23
|
-
|
|
24
|
-
{{> setupGit}}
|
|
25
|
-
{{> setupNode}}
|
|
26
|
-
{{> setupDeps}}
|
|
22
|
+
{{> setupJob }}
|
|
27
23
|
- name: Release Please
|
|
28
24
|
id: release
|
|
29
25
|
run: npx --offline template-oss-release-please $\{{ github.ref_name }}
|
|
@@ -40,34 +36,29 @@ jobs:
|
|
|
40
36
|
- name: Output ref
|
|
41
37
|
id: ref
|
|
42
38
|
run: echo "::set-output name=branch::$\{{ fromJSON(needs.release-please.outputs.pr).headBranchName }}"
|
|
43
|
-
{{> setupGit
|
|
39
|
+
{{> setupGit checkout=(obj ref="${{ steps.ref.outputs.branch }}" fetch-depth=0)}}
|
|
44
40
|
{{> setupNode}}
|
|
45
41
|
{{> setupDeps}}
|
|
46
42
|
- name: Post pull request actions
|
|
47
43
|
env:
|
|
48
44
|
GITHUB_TOKEN: $\{{ secrets.GITHUB_TOKEN }}
|
|
49
45
|
run: |
|
|
50
|
-
|
|
46
|
+
{{rootNpmPath}} run rp-pull-request --ignore-scripts --if-present -ws -iwr
|
|
51
47
|
git commit -am "chore: post pull request" || true
|
|
52
48
|
git push
|
|
53
49
|
|
|
54
50
|
release-test:
|
|
55
51
|
needs: post-pr
|
|
56
52
|
if: needs.post-pr.outputs.ref
|
|
57
|
-
uses: ./.github/workflows/
|
|
53
|
+
uses: ./.github/workflows/release.yml
|
|
58
54
|
with:
|
|
59
55
|
ref: $\{{ needs.post-pr.outputs.ref }}
|
|
60
56
|
|
|
61
57
|
post-release:
|
|
62
58
|
needs: release-please
|
|
63
|
-
|
|
64
|
-
runs-on: ubuntu-latest
|
|
65
|
-
steps:
|
|
66
|
-
{{> setupGit}}
|
|
67
|
-
{{> setupNode}}
|
|
68
|
-
{{> setupDeps}}
|
|
59
|
+
{{> setupJob jobIf="needs.release-please.outputs.release" }}
|
|
69
60
|
- name: Post release actions
|
|
70
61
|
env:
|
|
71
62
|
GITHUB_TOKEN: $\{{ secrets.GITHUB_TOKEN }}
|
|
72
63
|
run: |
|
|
73
|
-
|
|
64
|
+
{{rootNpmPath}} run rp-release --ignore-scripts --if-present -ws -iwr
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
|
|
2
|
+
name: Release
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
workflow_call:
|
|
6
|
+
inputs:
|
|
7
|
+
ref:
|
|
8
|
+
required: true
|
|
9
|
+
type: string
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
lint-all:
|
|
13
|
+
{{> setupJob checkout=(obj ref="${{ inputs.ref }}")}}
|
|
14
|
+
- run: {{rootNpmPath}} run lint -ws -iwr --if-present
|
|
15
|
+
|
|
16
|
+
test-all:
|
|
17
|
+
{{> setupJobMatrix checkout=(obj ref="${{ inputs.ref }}")}}
|
|
18
|
+
- name: add tap problem matcher
|
|
19
|
+
run: echo "::add-matcher::.github/matchers/tap.json"
|
|
20
|
+
- run: {{rootNpmPath}} run test -ws -iwr --if-present
|
package/lib/index.js
CHANGED
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
const log = require('proc-log')
|
|
2
|
-
const {
|
|
2
|
+
const { resolve } = require('path')
|
|
3
3
|
const getConfig = require('./config.js')
|
|
4
4
|
const PackageJson = require('@npmcli/package-json')
|
|
5
5
|
const mapWorkspaces = require('@npmcli/map-workspaces')
|
|
6
6
|
|
|
7
|
-
const getPkg = async (path
|
|
7
|
+
const getPkg = async (path) => {
|
|
8
8
|
log.verbose('get-pkg', path)
|
|
9
9
|
|
|
10
10
|
const pkg = (await PackageJson.load(path)).content
|
|
11
11
|
const pkgConfig = getConfig.getPkgConfig(pkg)
|
|
12
12
|
log.verbose('get-pkg', pkgConfig)
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
if (pkgConfig.content) {
|
|
15
|
+
pkgConfig.content = resolve(path, pkgConfig.content)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
pkg,
|
|
20
|
+
path,
|
|
21
|
+
config: pkgConfig,
|
|
22
|
+
}
|
|
15
23
|
}
|
|
16
24
|
|
|
17
25
|
const getWsPkgs = async (root, rootPkg) => {
|
|
@@ -45,38 +53,30 @@ const getPkgs = async (root) => {
|
|
|
45
53
|
log.verbose('get-pkgs', 'root', root)
|
|
46
54
|
|
|
47
55
|
const rootPkg = await getPkg(root)
|
|
48
|
-
const pkgs = [rootPkg]
|
|
49
|
-
|
|
50
|
-
defaults(rootPkg.config, {
|
|
51
|
-
rootRepo: true,
|
|
52
|
-
rootModule: true,
|
|
53
|
-
workspaceRepo: true,
|
|
54
|
-
workspaceModule: true,
|
|
55
|
-
workspaces: null,
|
|
56
|
-
})
|
|
57
56
|
|
|
58
57
|
const ws = await getWsPkgs(root, rootPkg)
|
|
59
58
|
|
|
60
59
|
return {
|
|
61
|
-
|
|
60
|
+
rootPkg,
|
|
61
|
+
pkgs: [rootPkg].concat(ws.pkgs),
|
|
62
62
|
workspaces: ws.paths,
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
const runAll = async (root,
|
|
66
|
+
const runAll = async (root, checks) => {
|
|
67
67
|
const results = []
|
|
68
|
-
const { pkgs, workspaces } = await getPkgs(root)
|
|
68
|
+
const { pkgs, workspaces, rootPkg: { config: rootConfig } } = await getPkgs(root)
|
|
69
69
|
|
|
70
|
-
for (const { pkg, path, config } of pkgs) {
|
|
70
|
+
for (const { pkg, path, config: pkgConfig } of pkgs) {
|
|
71
71
|
// full config includes original config values
|
|
72
72
|
const fullConfig = await getConfig({
|
|
73
|
-
pkgs,
|
|
74
|
-
workspaces,
|
|
75
73
|
root,
|
|
76
|
-
pkg,
|
|
77
74
|
path,
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
pkg,
|
|
76
|
+
pkgs,
|
|
77
|
+
workspaces,
|
|
78
|
+
rootConfig,
|
|
79
|
+
pkgConfig,
|
|
80
80
|
})
|
|
81
81
|
|
|
82
82
|
const options = { root, pkg, path, config: fullConfig }
|
|
@@ -10,35 +10,39 @@ module.exports = (gh) => {
|
|
|
10
10
|
return response
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
try {
|
|
14
|
+
const { repository } = await gh.graphql(
|
|
15
|
+
`fragment CommitAuthors on GitObject {
|
|
16
|
+
... on Commit {
|
|
17
|
+
authors (first:10) {
|
|
18
|
+
nodes {
|
|
19
|
+
user { login }
|
|
20
|
+
name
|
|
21
|
+
}
|
|
20
22
|
}
|
|
21
23
|
}
|
|
22
24
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
25
|
+
query {
|
|
26
|
+
repository (owner:"${owner}", name:"${repo}") {
|
|
27
|
+
${shas.map((s) => {
|
|
28
|
+
return `_${s}: object (expression: "${s}") { ...CommitAuthors }`
|
|
29
|
+
})}
|
|
30
|
+
}
|
|
31
|
+
}`
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
for (const [key, commit] of Object.entries(repository)) {
|
|
35
|
+
if (commit) {
|
|
36
|
+
response[key.slice(1)] = commit.authors.nodes
|
|
37
|
+
.map((a) => a.user && a.user.login ? `@${a.user.login}` : a.name)
|
|
38
|
+
.filter(Boolean)
|
|
29
39
|
}
|
|
30
|
-
}`
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
for (const [key, commit] of Object.entries(repository)) {
|
|
34
|
-
if (commit) {
|
|
35
|
-
response[key.slice(1)] = commit.authors.nodes
|
|
36
|
-
.map((a) => a.user && a.user.login ? `@${a.user.login}` : a.name)
|
|
37
|
-
.filter(Boolean)
|
|
38
40
|
}
|
|
39
|
-
}
|
|
40
41
|
|
|
41
|
-
|
|
42
|
+
return response
|
|
43
|
+
} catch {
|
|
44
|
+
return response
|
|
45
|
+
}
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
const url = (...p) => `https://github.com/${owner}/${repo}/${p.join('/')}`
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const localeCompare = require('@isaacs/string-locale-compare')('en')
|
|
1
2
|
const { NodeWorkspace } = require('release-please/build/src/plugins/node-workspace.js')
|
|
2
3
|
const { RawContent } = require('release-please/build/src/updaters/raw-content.js')
|
|
3
4
|
const { jsonStringify } = require('release-please/build/src/util/json-stringify.js')
|
|
@@ -105,9 +106,11 @@ module.exports = class extends NodeWorkspace {
|
|
|
105
106
|
// except it only updates the package.json instead of appending
|
|
106
107
|
// anything to changelogs since we've already done that in preconfigure.
|
|
107
108
|
updateCandidate (candidate, pkg, updatedVersions) {
|
|
109
|
+
const newVersion = updatedVersions.get(pkg.name)
|
|
108
110
|
const graphPackage = this.packageGraph.get(pkg.name)
|
|
109
|
-
const updatedPackage = pkg.clone()
|
|
110
111
|
|
|
112
|
+
const updatedPackage = pkg.clone()
|
|
113
|
+
updatedPackage.version = newVersion.toString()
|
|
111
114
|
for (const [depName, resolved] of graphPackage.localDependencies) {
|
|
112
115
|
const depVersion = updatedVersions.get(depName)
|
|
113
116
|
if (depVersion && resolved.type !== 'directory') {
|
|
@@ -160,10 +163,13 @@ module.exports = class extends NodeWorkspace {
|
|
|
160
163
|
if (aPath === ROOT_PROJECT_PATH) {
|
|
161
164
|
return -1
|
|
162
165
|
}
|
|
166
|
+
// release please pre sorts based on graph order so
|
|
167
|
+
// this is never called in normal circumstances
|
|
168
|
+
/* istanbul ignore next */
|
|
163
169
|
if (bPath === ROOT_PROJECT_PATH) {
|
|
164
170
|
return 1
|
|
165
171
|
}
|
|
166
|
-
return
|
|
172
|
+
return localeCompare(aPath, bPath)
|
|
167
173
|
})
|
|
168
174
|
}
|
|
169
175
|
|
package/lib/util/files.js
CHANGED
|
@@ -1,43 +1,55 @@
|
|
|
1
1
|
const { join } = require('path')
|
|
2
|
+
const { defaultsDeep } = require('lodash')
|
|
2
3
|
const { promisify } = require('util')
|
|
4
|
+
const merge = require('./merge.js')
|
|
5
|
+
const deepMapValues = require('just-deep-map-values')
|
|
3
6
|
const glob = promisify(require('glob'))
|
|
4
7
|
const Parser = require('./parser.js')
|
|
5
8
|
const template = require('./template.js')
|
|
6
9
|
|
|
10
|
+
const FILE_KEYS = ['rootRepo', 'rootModule', 'workspaceRepo', 'workspaceModule']
|
|
11
|
+
|
|
7
12
|
const globify = pattern => pattern.split('\\').join('/')
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
|
|
14
|
+
const fileEntries = (dir, files, options) => Object.entries(files)
|
|
15
|
+
// remove any false values
|
|
16
|
+
.filter(([_, v]) => v !== false)
|
|
17
|
+
// target paths need to be joinsed with dir and templated
|
|
18
|
+
.map(([k, source]) => {
|
|
19
|
+
const target = join(dir, template(k, options))
|
|
20
|
+
return [target, source]
|
|
21
|
+
})
|
|
11
22
|
|
|
12
23
|
// given an obj of files, return the full target/source paths and associated parser
|
|
13
|
-
const getParsers = (dir, files, options) =>
|
|
14
|
-
|
|
15
|
-
file,
|
|
16
|
-
|
|
17
|
-
filter
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
file = join(options.config.sourceDir, file)
|
|
21
|
-
const target = fullTarget(dir, t, options)
|
|
22
|
-
|
|
23
|
-
if (typeof filter === 'function' && !filter(options)) {
|
|
24
|
-
return null
|
|
25
|
-
}
|
|
24
|
+
const getParsers = (dir, files, options) => {
|
|
25
|
+
const parsers = fileEntries(dir, files, options).map(([target, source]) => {
|
|
26
|
+
const { file, parser, filter } = source
|
|
27
|
+
|
|
28
|
+
if (typeof filter === 'function' && !filter(options)) {
|
|
29
|
+
return null
|
|
30
|
+
}
|
|
26
31
|
|
|
27
|
-
|
|
32
|
+
if (parser) {
|
|
28
33
|
// allow files to extend base parsers or create new ones
|
|
29
|
-
|
|
30
|
-
|
|
34
|
+
return new (parser(Parser.Parsers))(target, file, options)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return new (Parser(file))(target, file, options)
|
|
38
|
+
})
|
|
31
39
|
|
|
32
|
-
return
|
|
33
|
-
}
|
|
40
|
+
return parsers.filter(Boolean)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const getRemovals = async (dir, files, options) => {
|
|
44
|
+
const targets = fileEntries(dir, files, options).map(([t]) => globify(t))
|
|
45
|
+
const globs = await Promise.all(targets.map(t => glob(t, { cwd: dir })))
|
|
46
|
+
return globs.flat()
|
|
47
|
+
}
|
|
34
48
|
|
|
35
49
|
const rmEach = async (dir, files, options, fn) => {
|
|
36
50
|
const res = []
|
|
37
|
-
for (const
|
|
38
|
-
|
|
39
|
-
res.push(await fn(file))
|
|
40
|
-
}
|
|
51
|
+
for (const file of await getRemovals(dir, files, options)) {
|
|
52
|
+
res.push(await fn(file))
|
|
41
53
|
}
|
|
42
54
|
return res.filter(Boolean)
|
|
43
55
|
}
|
|
@@ -45,14 +57,44 @@ const rmEach = async (dir, files, options, fn) => {
|
|
|
45
57
|
const parseEach = async (dir, files, options, fn) => {
|
|
46
58
|
const res = []
|
|
47
59
|
for (const parser of getParsers(dir, files, options)) {
|
|
48
|
-
|
|
49
|
-
res.push(await fn(parser))
|
|
50
|
-
}
|
|
60
|
+
res.push(await fn(parser))
|
|
51
61
|
}
|
|
52
62
|
return res.filter(Boolean)
|
|
53
63
|
}
|
|
54
64
|
|
|
65
|
+
const parseConfig = (files, dir, overrides) => {
|
|
66
|
+
const normalizeFiles = (v) => deepMapValues(v, (value, key) => {
|
|
67
|
+
if (key === 'rm' && Array.isArray(value)) {
|
|
68
|
+
return value.reduce((acc, k) => {
|
|
69
|
+
acc[k] = true
|
|
70
|
+
return acc
|
|
71
|
+
}, {})
|
|
72
|
+
}
|
|
73
|
+
if (typeof value === 'string') {
|
|
74
|
+
const file = join(dir, value)
|
|
75
|
+
return key === 'file' ? file : { file }
|
|
76
|
+
}
|
|
77
|
+
if (value === true && FILE_KEYS.includes(key)) {
|
|
78
|
+
return {}
|
|
79
|
+
}
|
|
80
|
+
return value
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
const merged = merge(normalizeFiles(files), normalizeFiles(overrides))
|
|
84
|
+
const withDefaults = defaultsDeep(merged, FILE_KEYS.reduce((acc, k) => {
|
|
85
|
+
acc[k] = { add: {}, rm: {} }
|
|
86
|
+
return acc
|
|
87
|
+
}, {}))
|
|
88
|
+
|
|
89
|
+
return withDefaults
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const getAddedFiles = (files) => files ? Object.keys(files.add || {}) : []
|
|
93
|
+
|
|
55
94
|
module.exports = {
|
|
56
95
|
rmEach,
|
|
57
96
|
parseEach,
|
|
97
|
+
FILE_KEYS,
|
|
98
|
+
parseConfig,
|
|
99
|
+
getAddedFiles,
|
|
58
100
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const { posix } = require('path')
|
|
2
|
+
const { uniq } = require('lodash')
|
|
3
|
+
const localeCompare = require('@isaacs/string-locale-compare')('en')
|
|
4
|
+
|
|
5
|
+
const sortGitPaths = (a, b) => localeCompare(a.replace(/^!/g, ''), b.replace(/^!/g, ''))
|
|
6
|
+
|
|
7
|
+
const allowDir = (p) => {
|
|
8
|
+
const parts = p.split(posix.sep)
|
|
9
|
+
return parts.flatMap((part, index, list) => {
|
|
10
|
+
const prev = list.slice(0, index)
|
|
11
|
+
const isLast = index === list.length - 1
|
|
12
|
+
const ignorePart = ['', ...prev, part, ''].join(posix.sep)
|
|
13
|
+
return [`!${ignorePart}`, !isLast && `${ignorePart}*`]
|
|
14
|
+
}).filter(Boolean)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const allowRootDir = (p) => {
|
|
18
|
+
// This negates the first part of each path for the gitignore
|
|
19
|
+
// files. It should be used to allow directories where everything
|
|
20
|
+
// should be allowed inside such as .github/. It shouldn't be used on
|
|
21
|
+
// directories like `workspaces/` since we want to be explicit and
|
|
22
|
+
// only allow each workspace directory individually. For those use
|
|
23
|
+
// the allowDir method above.
|
|
24
|
+
const [first, hasChildren] = p.split(posix.sep)
|
|
25
|
+
return `${first}${hasChildren ? posix.sep : ''}`
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const gitignore = {
|
|
29
|
+
allowDir: (dirs) => uniq(dirs.map(allowDir).flat()),
|
|
30
|
+
allowRootDir: (dirs) => dirs.map(allowRootDir).map((p) => `!${posix.sep}${p}`),
|
|
31
|
+
sort: (arr) => uniq(arr.sort(sortGitPaths)),
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = gitignore
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const { mergeWith } = require('lodash')
|
|
2
|
+
|
|
3
|
+
const merge = (...objects) => mergeWith({}, ...objects, (value, srcValue, key) => {
|
|
4
|
+
if (Array.isArray(srcValue)) {
|
|
5
|
+
// Dont merge arrays, last array wins
|
|
6
|
+
return srcValue
|
|
7
|
+
}
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
const mergeWithArrays = (...keys) =>
|
|
11
|
+
(...objects) => mergeWith({}, ...objects, (value, srcValue, key) => {
|
|
12
|
+
if (Array.isArray(srcValue)) {
|
|
13
|
+
if (keys.includes(key)) {
|
|
14
|
+
return (Array.isArray(value) ? value : []).concat(srcValue)
|
|
15
|
+
}
|
|
16
|
+
return srcValue
|
|
17
|
+
}
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
module.exports = merge
|
|
21
|
+
module.exports.withArrays = mergeWithArrays
|
package/lib/util/parser.js
CHANGED
|
@@ -4,9 +4,10 @@ const yaml = require('yaml')
|
|
|
4
4
|
const NpmPackageJson = require('@npmcli/package-json')
|
|
5
5
|
const jsonParse = require('json-parse-even-better-errors')
|
|
6
6
|
const Diff = require('diff')
|
|
7
|
-
const { unset
|
|
7
|
+
const { unset } = require('lodash')
|
|
8
8
|
const template = require('./template.js')
|
|
9
9
|
const jsonDiff = require('./json-diff')
|
|
10
|
+
const merge = require('./merge.js')
|
|
10
11
|
const setFirst = (first, rest) => ({ ...first, ...rest })
|
|
11
12
|
const traverse = (value, visit, keys = []) => {
|
|
12
13
|
if (keys.length) {
|
|
@@ -220,7 +221,7 @@ class Json extends Base {
|
|
|
220
221
|
|
|
221
222
|
class JsonMerge extends Json {
|
|
222
223
|
static header = 'This file is partially managed by {{__NAME__}}. Edits may be overwritten.'
|
|
223
|
-
merge = (t, s) => merge(
|
|
224
|
+
merge = (t, s) => merge(t, s)
|
|
224
225
|
}
|
|
225
226
|
|
|
226
227
|
class PackageJson extends JsonMerge {
|