@npmcli/template-oss 4.1.2 → 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.
@@ -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-test.yml': {
9
- file: 'release-test.yml',
10
- filter: (o) => !o.pkg.private && o.config.releaseTest === 'release-test.yml',
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(true),
69
- '.github/matchers/tap.json': 'tap.json',
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
- // Escape hatch since we write a release test file but the
102
- // CLI has a very custom one we dont want to overwrite. This
103
- // setting allows us to call a workflow by any name during release
104
- releaseTest: 'release-test.yml',
105
- distPaths: ['bin/', 'lib/'],
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
- npmBin: 'npm',
129
+ npm: 'npm',
130
+ npx: 'npx',
109
131
  unwantedPackages: [
110
132
  'eslint',
111
133
  'eslint-plugin-node',
@@ -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": "{{npmBin}} run lint -- --fix",
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": "{{npmBin}} run lint",
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
- runs-on: ubuntu-latest
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
- npm run template-oss-apply
23
+ {{rootNpmPath}} run template-oss-apply
29
24
  git commit -am "chore: postinstall for dependabot template-oss PR"
30
25
  git push
31
- npm run lint
26
+ {{rootNpmPath}} run lint
@@ -11,14 +11,10 @@ on:
11
11
  jobs:
12
12
  check:
13
13
  name: Check PR Title or Commits
14
- runs-on: ubuntu-latest
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
- npx --offline commitlint -V --from origin/{{defaultBranch}} --to $\{{ github.event.pull_request.head.sha }} \
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
- steps:
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 with=(obj ref="${{ steps.ref.outputs.branch }}" fetch-depth=0)}}
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
- npm run rp-pull-request --ignore-scripts --if-present -ws -iwr
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/{{releaseTest}}
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
- if: needs.release-please.outputs.release
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
- npm run rp-release --ignore-scripts --if-present -ws -iwr
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 { defaults } = require('lodash')
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, baseConfig) => {
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
- return { pkg, path, config: { ...baseConfig, ...pkgConfig } }
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
- pkgs: pkgs.concat(ws.pkgs),
60
+ rootPkg,
61
+ pkgs: [rootPkg].concat(ws.pkgs),
62
62
  workspaces: ws.paths,
63
63
  }
64
64
  }
65
65
 
66
- const runAll = async (root, content, checks) => {
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
- config,
79
- content,
75
+ pkg,
76
+ pkgs,
77
+ workspaces,
78
+ rootConfig,
79
+ pkgConfig,
80
80
  })
81
81
 
82
82
  const options = { root, pkg, path, config: fullConfig }
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
- // target paths need to be joinsed with dir and templated
10
- const fullTarget = (dir, file, options) => join(dir, template(file, options))
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) => Object.entries(files).map(([t, s]) => {
14
- let {
15
- file,
16
- parser: fileParser,
17
- filter,
18
- } = typeof s === 'string' ? { file: s } : s
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
- if (fileParser) {
32
+ if (parser) {
28
33
  // allow files to extend base parsers or create new ones
29
- return new (fileParser(Parser.Parsers))(target, file, options)
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 new (Parser(file))(target, file, options)
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 target of files.map((t) => fullTarget(dir, t, options))) {
38
- for (const file of await glob(globify(target), { cwd: dir })) {
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
- if (parser) {
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
@@ -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, merge } = require('lodash')
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({}, t, s)
224
+ merge = (t, s) => merge(t, s)
224
225
  }
225
226
 
226
227
  class PackageJson extends JsonMerge {
@@ -3,35 +3,37 @@ const { basename, extname, join } = require('path')
3
3
  const fs = require('fs')
4
4
  const DELETE = '__DELETE__'
5
5
 
6
- const partialName = (s) =>
7
- basename(s, extname(s)).replace(/-([a-z])/g, (_, g) => g.toUpperCase())
6
+ const partialName = (s) => basename(s, extname(s)) // remove extension
7
+ .replace(/^_/, '') // remove leading underscore
8
+ .replace(/-([a-z])/g, (_, g) => g.toUpperCase()) // camelcase
8
9
 
9
- const setupHandlebars = (partialsDir) => {
10
+ const setupHandlebars = (...partialDirs) => {
10
11
  Handlebars.registerHelper('obj', ({ hash }) => hash)
11
12
  Handlebars.registerHelper('json', (c) => JSON.stringify(c))
12
13
  Handlebars.registerHelper('del', () => JSON.stringify(DELETE))
13
14
 
14
- // Load all content files as camelcase partial names
15
- for (const f of fs.readdirSync(join(partialsDir))) {
16
- Handlebars.registerPartial(
17
- partialName(f),
18
- fs.readFileSync(join(partialsDir, f)).toString()
19
- )
15
+ // Load all files as camelcase partial names.
16
+ // all other content dirs only get special underscore leading
17
+ // files as partials. this prevents recursion loops when overwriting
18
+ // a filename to use as a enw file
19
+ let isBase = true
20
+ for (const dir of partialDirs) {
21
+ for (const f of fs.readdirSync(dir)) {
22
+ if (f.startsWith('_') || isBase) {
23
+ Handlebars.registerPartial(
24
+ partialName(f),
25
+ fs.readFileSync(join(dir, f)).toString()
26
+ )
27
+ }
28
+ }
29
+ isBase = false
20
30
  }
21
31
  }
22
32
 
23
- const cache = new Map()
24
-
25
33
  const template = (str, { config, ...options }) => {
26
- if (cache.size === 0) {
27
- setupHandlebars(config.sourceDir)
28
- }
34
+ setupHandlebars(...config.__PARTIAL_DIRS__)
29
35
 
30
- let t = cache.get(str)
31
- if (t == null) {
32
- t = Handlebars.compile(str, { strict: true })
33
- cache.set(str, t)
34
- }
36
+ const t = Handlebars.compile(str, { strict: true })
35
37
 
36
38
  // merge in config as top level data in templates
37
39
  return t({ ...options, ...config })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@npmcli/template-oss",
3
- "version": "4.1.2",
3
+ "version": "4.2.0",
4
4
  "description": "templated files used in npm CLI team oss projects",
5
5
  "main": "lib/content/index.js",
6
6
  "bin": {
@@ -42,6 +42,7 @@
42
42
  "handlebars": "^4.7.7",
43
43
  "hosted-git-info": "^5.0.0",
44
44
  "json-parse-even-better-errors": "^2.3.1",
45
+ "just-deep-map-values": "^1.1.1",
45
46
  "just-diff": "^5.0.1",
46
47
  "lodash": "^4.17.21",
47
48
  "npm-package-arg": "^9.0.1",
@@ -60,7 +61,11 @@
60
61
  "tap": "^16.0.0"
61
62
  },
62
63
  "tap": {
63
- "timeout": 600
64
+ "timeout": 600,
65
+ "nyc-arg": [
66
+ "--exclude",
67
+ "tap-snapshots/**"
68
+ ]
64
69
  },
65
70
  "templateOSS": {
66
71
  "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten."
@@ -1,46 +0,0 @@
1
- name: Release
2
-
3
- on:
4
- workflow_call:
5
- inputs:
6
- ref:
7
- required: true
8
- type: string
9
-
10
- jobs:
11
- lint-all:
12
- runs-on: ubuntu-latest
13
- steps:
14
- {{> setupGit with=(obj ref="${{ inputs.ref }}")}}
15
- {{> setupNode}}
16
- {{> setupDeps}}
17
- - run: npm run lint --if-present --workspaces --include-workspace-root
18
-
19
- test-all:
20
- strategy:
21
- fail-fast: false
22
- matrix:
23
- node-version:
24
- {{#each ciVersions}}
25
- - {{.}}
26
- {{/each}}
27
- platform:
28
- - os: ubuntu-latest
29
- shell: bash
30
- - os: macos-latest
31
- shell: bash
32
- {{#if windowsCI}}
33
- - os: windows-latest
34
- shell: cmd
35
- {{/if}}
36
- runs-on: $\{{ matrix.platform.os }}
37
- defaults:
38
- run:
39
- shell: $\{{ matrix.platform.shell }}
40
- steps:
41
- {{> setupGit with=(obj ref="${{ inputs.ref }}")}}
42
- {{> setupNode useMatrix=true}}
43
- {{> setupDeps}}
44
- - name: add tap problem matcher
45
- run: echo "::add-matcher::.github/matchers/tap.json"
46
- - run: npm run test --if-present --workspaces --include-workspace-root