11cb0ef41Sopenharmony_ci/* globals config, dirname, package, basename, yes, prompt */
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst fs = require('fs/promises')
41cb0ef41Sopenharmony_ciconst path = require('path')
51cb0ef41Sopenharmony_ciconst validateLicense = require('validate-npm-package-license')
61cb0ef41Sopenharmony_ciconst validateName = require('validate-npm-package-name')
71cb0ef41Sopenharmony_ciconst npa = require('npm-package-arg')
81cb0ef41Sopenharmony_ciconst semver = require('semver')
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci// more popular packages should go here, maybe?
111cb0ef41Sopenharmony_ciconst isTestPkg = (p) => !!p.match(/^(expresso|mocha|tap|coffee-script|coco|streamline)$/)
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ciconst invalid = (msg) => Object.assign(new Error(msg), { notValid: true })
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ciconst readDeps = (test, excluded) => async () => {
161cb0ef41Sopenharmony_ci  const dirs = await fs.readdir('node_modules').catch(() => null)
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ci  if (!dirs) {
191cb0ef41Sopenharmony_ci    return
201cb0ef41Sopenharmony_ci  }
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci  const deps = {}
231cb0ef41Sopenharmony_ci  for (const dir of dirs) {
241cb0ef41Sopenharmony_ci    if (dir.match(/^\./) || test !== isTestPkg(dir) || excluded[dir]) {
251cb0ef41Sopenharmony_ci      continue
261cb0ef41Sopenharmony_ci    }
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci    const dp = path.join(dirname, 'node_modules', dir, 'package.json')
291cb0ef41Sopenharmony_ci    const p = await fs.readFile(dp, 'utf8').then((d) => JSON.parse(d)).catch(() => null)
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci    if (!p || !p.version || p?._requiredBy?.some((r) => r === '#USER')) {
321cb0ef41Sopenharmony_ci      continue
331cb0ef41Sopenharmony_ci    }
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci    deps[dir] = config.get('save-exact') ? p.version : config.get('save-prefix') + p.version
361cb0ef41Sopenharmony_ci  }
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci  return deps
391cb0ef41Sopenharmony_ci}
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ciconst getConfig = (key) => {
421cb0ef41Sopenharmony_ci  // dots take precedence over dashes
431cb0ef41Sopenharmony_ci  const def = config?.defaults?.[`init.${key}`]
441cb0ef41Sopenharmony_ci  const val = config.get(`init.${key}`)
451cb0ef41Sopenharmony_ci  return (val !== def && val) ? val : config.get(`init-${key.replace(/\./g, '-')}`)
461cb0ef41Sopenharmony_ci}
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ciconst getName = () => {
491cb0ef41Sopenharmony_ci  const rawName = package.name || basename
501cb0ef41Sopenharmony_ci  let name = rawName
511cb0ef41Sopenharmony_ci    .replace(/^node-|[.-]js$/g, '')
521cb0ef41Sopenharmony_ci    .replace(/\s+/g, ' ')
531cb0ef41Sopenharmony_ci    .replace(/ /g, '-')
541cb0ef41Sopenharmony_ci    .toLowerCase()
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci  let spec
571cb0ef41Sopenharmony_ci  try {
581cb0ef41Sopenharmony_ci    spec = npa(name)
591cb0ef41Sopenharmony_ci  } catch {
601cb0ef41Sopenharmony_ci    spec = {}
611cb0ef41Sopenharmony_ci  }
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci  let scope = config.get('scope')
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci  if (scope) {
661cb0ef41Sopenharmony_ci    if (scope.charAt(0) !== '@') {
671cb0ef41Sopenharmony_ci      scope = '@' + scope
681cb0ef41Sopenharmony_ci    }
691cb0ef41Sopenharmony_ci    if (spec.scope) {
701cb0ef41Sopenharmony_ci      name = scope + '/' + spec.name.split('/')[1]
711cb0ef41Sopenharmony_ci    } else {
721cb0ef41Sopenharmony_ci      name = scope + '/' + name
731cb0ef41Sopenharmony_ci    }
741cb0ef41Sopenharmony_ci  }
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  return name
771cb0ef41Sopenharmony_ci}
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ciconst name = getName()
801cb0ef41Sopenharmony_ciexports.name = yes ? name : prompt('package name', name, (data) => {
811cb0ef41Sopenharmony_ci  const its = validateName(data)
821cb0ef41Sopenharmony_ci  if (its.validForNewPackages) {
831cb0ef41Sopenharmony_ci    return data
841cb0ef41Sopenharmony_ci  }
851cb0ef41Sopenharmony_ci  const errors = (its.errors || []).concat(its.warnings || [])
861cb0ef41Sopenharmony_ci  return invalid(`Sorry, ${errors.join(' and ')}.`)
871cb0ef41Sopenharmony_ci})
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ciconst version = package.version || getConfig('version') || '1.0.0'
901cb0ef41Sopenharmony_ciexports.version = yes ? version : prompt('version', version, (v) => {
911cb0ef41Sopenharmony_ci  if (semver.valid(v)) {
921cb0ef41Sopenharmony_ci    return v
931cb0ef41Sopenharmony_ci  }
941cb0ef41Sopenharmony_ci  return invalid(`Invalid version: "${v}"`)
951cb0ef41Sopenharmony_ci})
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ciif (!package.description) {
981cb0ef41Sopenharmony_ci  exports.description = yes ? '' : prompt('description')
991cb0ef41Sopenharmony_ci}
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ciif (!package.main) {
1021cb0ef41Sopenharmony_ci  exports.main = async () => {
1031cb0ef41Sopenharmony_ci    const files = await fs.readdir(dirname)
1041cb0ef41Sopenharmony_ci      .then(list => list.filter((f) => f.match(/\.js$/)))
1051cb0ef41Sopenharmony_ci      .catch(() => [])
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci    let index
1081cb0ef41Sopenharmony_ci    if (files.includes('index.js')) {
1091cb0ef41Sopenharmony_ci      index = 'index.js'
1101cb0ef41Sopenharmony_ci    } else if (files.includes('main.js')) {
1111cb0ef41Sopenharmony_ci      index = 'main.js'
1121cb0ef41Sopenharmony_ci    } else if (files.includes(basename + '.js')) {
1131cb0ef41Sopenharmony_ci      index = basename + '.js'
1141cb0ef41Sopenharmony_ci    } else {
1151cb0ef41Sopenharmony_ci      index = files[0] || 'index.js'
1161cb0ef41Sopenharmony_ci    }
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci    return yes ? index : prompt('entry point', index)
1191cb0ef41Sopenharmony_ci  }
1201cb0ef41Sopenharmony_ci}
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ciif (!package.bin) {
1231cb0ef41Sopenharmony_ci  exports.bin = async () => {
1241cb0ef41Sopenharmony_ci    try {
1251cb0ef41Sopenharmony_ci      const d = await fs.readdir(path.resolve(dirname, 'bin'))
1261cb0ef41Sopenharmony_ci      // just take the first js file we find there, or nada
1271cb0ef41Sopenharmony_ci      let r = d.find(f => f.match(/\.js$/))
1281cb0ef41Sopenharmony_ci      if (r) {
1291cb0ef41Sopenharmony_ci        r = `bin/${r}`
1301cb0ef41Sopenharmony_ci      }
1311cb0ef41Sopenharmony_ci      return r
1321cb0ef41Sopenharmony_ci    } catch {
1331cb0ef41Sopenharmony_ci      // no bins
1341cb0ef41Sopenharmony_ci    }
1351cb0ef41Sopenharmony_ci  }
1361cb0ef41Sopenharmony_ci}
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ciexports.directories = async () => {
1391cb0ef41Sopenharmony_ci  const dirs = await fs.readdir(dirname)
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_ci  const res = dirs.reduce((acc, d) => {
1421cb0ef41Sopenharmony_ci    if (/^examples?$/.test(d)) {
1431cb0ef41Sopenharmony_ci      acc.example = d
1441cb0ef41Sopenharmony_ci    } else if (/^tests?$/.test(d)) {
1451cb0ef41Sopenharmony_ci      acc.test = d
1461cb0ef41Sopenharmony_ci    } else if (/^docs?$/.test(d)) {
1471cb0ef41Sopenharmony_ci      acc.doc = d
1481cb0ef41Sopenharmony_ci    } else if (d === 'man') {
1491cb0ef41Sopenharmony_ci      acc.man = d
1501cb0ef41Sopenharmony_ci    } else if (d === 'lib') {
1511cb0ef41Sopenharmony_ci      acc.lib = d
1521cb0ef41Sopenharmony_ci    }
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci    return acc
1551cb0ef41Sopenharmony_ci  }, {})
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci  return Object.keys(res).length === 0 ? undefined : res
1581cb0ef41Sopenharmony_ci}
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_ciif (!package.dependencies) {
1611cb0ef41Sopenharmony_ci  exports.dependencies = readDeps(false, package.devDependencies || {})
1621cb0ef41Sopenharmony_ci}
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ciif (!package.devDependencies) {
1651cb0ef41Sopenharmony_ci  exports.devDependencies = readDeps(true, package.dependencies || {})
1661cb0ef41Sopenharmony_ci}
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ci// MUST have a test script!
1691cb0ef41Sopenharmony_ciif (!package.scripts) {
1701cb0ef41Sopenharmony_ci  const scripts = package.scripts || {}
1711cb0ef41Sopenharmony_ci  const notest = 'echo "Error: no test specified" && exit 1'
1721cb0ef41Sopenharmony_ci  exports.scripts = async () => {
1731cb0ef41Sopenharmony_ci    const d = await fs.readdir(path.join(dirname, 'node_modules')).catch(() => [])
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci    // check to see what framework is in use, if any
1761cb0ef41Sopenharmony_ci    let command
1771cb0ef41Sopenharmony_ci    if (!scripts.test || scripts.test === notest) {
1781cb0ef41Sopenharmony_ci      const commands = {
1791cb0ef41Sopenharmony_ci        tap: 'tap test/*.js',
1801cb0ef41Sopenharmony_ci        expresso: 'expresso test',
1811cb0ef41Sopenharmony_ci        mocha: 'mocha',
1821cb0ef41Sopenharmony_ci      }
1831cb0ef41Sopenharmony_ci      for (const [k, v] of Object.entries(commands)) {
1841cb0ef41Sopenharmony_ci        if (d.includes(k)) {
1851cb0ef41Sopenharmony_ci          command = v
1861cb0ef41Sopenharmony_ci        }
1871cb0ef41Sopenharmony_ci      }
1881cb0ef41Sopenharmony_ci    }
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci    const promptArgs = ['test command', (t) => t || notest]
1911cb0ef41Sopenharmony_ci    if (command) {
1921cb0ef41Sopenharmony_ci      promptArgs.splice(1, 0, command)
1931cb0ef41Sopenharmony_ci    }
1941cb0ef41Sopenharmony_ci    scripts.test = yes ? command || notest : prompt(...promptArgs)
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci    return scripts
1971cb0ef41Sopenharmony_ci  }
1981cb0ef41Sopenharmony_ci}
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_ciif (!package.repository) {
2011cb0ef41Sopenharmony_ci  exports.repository = async () => {
2021cb0ef41Sopenharmony_ci    const gconf = await fs.readFile('.git/config', 'utf8').catch(() => '')
2031cb0ef41Sopenharmony_ci    const lines = gconf.split(/\r?\n/)
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ci    let url
2061cb0ef41Sopenharmony_ci    const i = lines.indexOf('[remote "origin"]')
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ci    if (i !== -1) {
2091cb0ef41Sopenharmony_ci      url = gconf[i + 1]
2101cb0ef41Sopenharmony_ci      if (!url.match(/^\s*url =/)) {
2111cb0ef41Sopenharmony_ci        url = gconf[i + 2]
2121cb0ef41Sopenharmony_ci      }
2131cb0ef41Sopenharmony_ci      if (!url.match(/^\s*url =/)) {
2141cb0ef41Sopenharmony_ci        url = null
2151cb0ef41Sopenharmony_ci      } else {
2161cb0ef41Sopenharmony_ci        url = url.replace(/^\s*url = /, '')
2171cb0ef41Sopenharmony_ci      }
2181cb0ef41Sopenharmony_ci    }
2191cb0ef41Sopenharmony_ci
2201cb0ef41Sopenharmony_ci    if (url && url.match(/^git@github.com:/)) {
2211cb0ef41Sopenharmony_ci      url = url.replace(/^git@github.com:/, 'https://github.com/')
2221cb0ef41Sopenharmony_ci    }
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ci    return yes ? url || '' : prompt('git repository', url || undefined)
2251cb0ef41Sopenharmony_ci  }
2261cb0ef41Sopenharmony_ci}
2271cb0ef41Sopenharmony_ci
2281cb0ef41Sopenharmony_ciif (!package.keywords) {
2291cb0ef41Sopenharmony_ci  exports.keywords = yes ? '' : prompt('keywords', (data) => {
2301cb0ef41Sopenharmony_ci    if (!data) {
2311cb0ef41Sopenharmony_ci      return
2321cb0ef41Sopenharmony_ci    }
2331cb0ef41Sopenharmony_ci    if (Array.isArray(data)) {
2341cb0ef41Sopenharmony_ci      data = data.join(' ')
2351cb0ef41Sopenharmony_ci    }
2361cb0ef41Sopenharmony_ci    if (typeof data !== 'string') {
2371cb0ef41Sopenharmony_ci      return data
2381cb0ef41Sopenharmony_ci    }
2391cb0ef41Sopenharmony_ci    return data.split(/[\s,]+/)
2401cb0ef41Sopenharmony_ci  })
2411cb0ef41Sopenharmony_ci}
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ciif (!package.author) {
2441cb0ef41Sopenharmony_ci  const authorName = getConfig('author.name')
2451cb0ef41Sopenharmony_ci  exports.author = authorName
2461cb0ef41Sopenharmony_ci    ? {
2471cb0ef41Sopenharmony_ci      name: authorName,
2481cb0ef41Sopenharmony_ci      email: getConfig('author.email'),
2491cb0ef41Sopenharmony_ci      url: getConfig('author.url'),
2501cb0ef41Sopenharmony_ci    }
2511cb0ef41Sopenharmony_ci    : yes ? '' : prompt('author')
2521cb0ef41Sopenharmony_ci}
2531cb0ef41Sopenharmony_ci
2541cb0ef41Sopenharmony_ciconst license = package.license || getConfig('license') || 'ISC'
2551cb0ef41Sopenharmony_ciexports.license = yes ? license : prompt('license', license, (data) => {
2561cb0ef41Sopenharmony_ci  const its = validateLicense(data)
2571cb0ef41Sopenharmony_ci  if (its.validForNewPackages) {
2581cb0ef41Sopenharmony_ci    return data
2591cb0ef41Sopenharmony_ci  }
2601cb0ef41Sopenharmony_ci  const errors = (its.errors || []).concat(its.warnings || [])
2611cb0ef41Sopenharmony_ci  return invalid(`Sorry, ${errors.join(' and ')}.`)
2621cb0ef41Sopenharmony_ci})
263