Skip to content

Commit

Permalink
feat: support rc files (#1067)
Browse files Browse the repository at this point in the history
* feat: support rc files

* chore: code review
  • Loading branch information
mdonnalley committed May 6, 2024
1 parent c70372a commit 6af9c71
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 2 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"ansis": "^3.0.1",
"clean-stack": "^3.0.1",
"cli-spinners": "^2.9.2",
"cosmiconfig": "^9.0.0",
"debug": "^4.3.4",
"ejs": "^3.1.10",
"get-package-type": "^0.1.0",
Expand Down
3 changes: 2 additions & 1 deletion src/config/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {SINGLE_COMMAND_CLI_SYMBOL} from '../symbols'
import {cacheCommand} from '../util/cache-command'
import {findRoot} from '../util/find-root'
import {readJson} from '../util/fs'
import {readPjson} from '../util/read-pjson'
import {castArray, compact} from '../util/util'
import {tsPath} from './ts-path'
import {getCommandIdPermutations, makeDebug} from './util'
Expand Down Expand Up @@ -224,7 +225,7 @@ export class Plugin implements IPlugin {
if (!root) throw new CLIError(`could not find package.json with ${inspect(this.options)}`)
this.root = root
this._debug(`loading ${this.type} plugin from ${root}`)
this.pjson = this.options.pjson ?? (await readJson(join(root, 'package.json')))
this.pjson = this.options.pjson ?? (await readPjson(root))
this.flexibleTaxonomy = this.options?.flexibleTaxonomy || this.pjson.oclif?.flexibleTaxonomy || false
this.moduleType = this.pjson.type === 'module' ? 'module' : 'commonjs'
this.name = this.pjson.name
Expand Down
2 changes: 1 addition & 1 deletion src/util/find-root.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ function findPnpRoot(name: string, root: string): string | undefined {
*
* If no path is found, undefined is returned which will eventually result in a thrown Error from Plugin.
*/
export async function findRoot(name: string | undefined, root: string) {
export async function findRoot(name: string | undefined, root: string): Promise<string | undefined> {
if (name) {
debug(name)(`Finding root using ${root}`)
let pkgPath
Expand Down
16 changes: 16 additions & 0 deletions src/util/fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,35 @@ export const fileExists = async (input: string): Promise<string> => {
return input
}

const cache = new Map<string, string>()

export async function readJson<T = unknown>(path: string): Promise<T> {
if (cache.has(path)) {
return JSON.parse(cache.get(path)!) as T
}

const contents = await readFile(path, 'utf8')
cache.set(path, contents)
return JSON.parse(contents) as T
}

export function readJsonSync(path: string, parse: false): string
export function readJsonSync<T = unknown>(path: string, parse?: true): T
export function readJsonSync<T = unknown>(path: string, parse = true): T | string {
if (cache.has(path)) {
return JSON.parse(cache.get(path)!) as T
}

const contents = readFileSync(path, 'utf8')
cache.set(path, contents)
return parse ? (JSON.parse(contents) as T) : contents
}

export async function safeReadJson<T>(path: string): Promise<T | undefined> {
if (cache.has(path)) {
return JSON.parse(cache.get(path)!) as T
}

try {
return await readJson<T>(path)
} catch {}
Expand Down
64 changes: 64 additions & 0 deletions src/util/read-pjson.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {cosmiconfig} from 'cosmiconfig'
import {join} from 'node:path'

import {PJSON} from '../interfaces'
import {makeDebug} from '../logger'
import {readJson} from './fs'

const debug = makeDebug('read-pjson')

/**
* Read the package.json file from a given path and add the oclif config (found by cosmiconfig) if it exists.
*
* We can assume that the package.json file exists because the plugin root has already been loaded at this point.
*/
export async function readPjson(path: string): Promise<PJSON.Plugin> {
const pjsonPath = join(path, 'package.json')
if (process.env.OCLIF_DISABLE_RC) {
debug('OCLIF_DISABLE_RC is set, skipping rc search')
return readJson<PJSON.Plugin>(pjsonPath)
}

const pjson = await readJson<PJSON.Plugin>(pjsonPath)

// don't bother with cosmiconfig if the plugin's package.json already has an oclif config
if (pjson.oclif) {
debug(`found oclif config in ${pjsonPath}`)
return pjson
}

debug(`searching for oclif config in ${path}`)
const explorer = cosmiconfig('oclif', {
/**
* Remove the following from the defaults:
* - package.json
* - any files under .config/
*/
searchPlaces: [
'.oclifrc',
'.oclifrc.json',
'.oclifrc.yaml',
'.oclifrc.yml',
'.oclifrc.js',
'.oclifrc.ts',
'.oclifrc.mjs',
'.oclifrc.cjs',
'oclif.config.js',
'oclif.config.ts',
'oclif.config.mjs',
'oclif.config.cjs',
],
searchStrategy: 'none',
})
const result = await explorer.search(path)
if (!result?.config) {
debug(`no oclif config found in ${path}`)
return pjson
}

debug(`found oclif config for ${path}: %O`, result)
return {
...pjson,
oclif: result?.config ?? {},
}
}

0 comments on commit 6af9c71

Please sign in to comment.