Skip to content
This repository was archived by the owner on Jun 11, 2022. It is now read-only.

Commit

Permalink
refactor: plugin improvments and only bootstrap if different text.
Browse files Browse the repository at this point in the history
closes #52
  • Loading branch information
hyperupcall committed Jun 26, 2020
1 parent 513e650 commit 67da875
Show file tree
Hide file tree
Showing 12 changed files with 257 additions and 86 deletions.
5 changes: 4 additions & 1 deletion fox.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
export default {
/** @type {import("fox-types/types").IFoxConfig} */
const foxConfig = {
all: "strict",
env: ["node"],
};

export default foxConfig
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@types/lodash.throttle": "^4.1.6",
"@types/lodash.uniq": "^4.5.6",
"@types/minimist": "^1.2.0",
"@types/mkdirp": "^1.0.1",
"@types/node": "^14.0.13",
"@types/prettier": "^2.0.1",
"@types/prompts": "^2.0.8",
Expand Down
53 changes: 36 additions & 17 deletions packages/fox-plugin-eslint/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as foxUtils from 'fox-utils'
import { ESLint } from 'eslint'
import type { IFoxConfig } from 'fox-types'
import fs from 'fs'
import merge from 'lodash.mergewith'
import mergewith from 'lodash.mergewith'

const { debug, log } = foxUtils
const d = debug('fox-suite:fox-plugin-eslint')
Expand Down Expand Up @@ -43,24 +43,27 @@ export async function fixFunction() {
const defaultConfig = (await import(
require.resolve('eslint-config-fox'))
).default
const userConfigModule = (await import(
require.resolve(path.join(project.location, '.config/eslint.config.js'))
))
if (typeof userConfigModule.default !== 'function') {
log.error('default export is not a function. skipping eslint')

const {
mergedConfig
} = await foxUtils.getConfigAndIgnores({
defaultConfig,
userConfigPath: require.resolve(path.join(project.location, '.config/eslint.config.js')),
configMergeFn: (defaultConfig, userConfig) => {
return mergewith(defaultConfig, userConfig, customizer)
}
})
if (!mergedConfig) {
log.error(`failed to merge config for fox-plugin-eslint. skipping.`)
return
}
const userConfig = userConfigModule.default(project.foxConfig)

const mergedConfig = merge(defaultConfig, userConfig, customizer)


await foxUtils.writeFile(
path.join(project.location, '.config/build/eslint.config.json'),
mergedConfig,
)

const eslint = new ESLint({
const eslintObj: ESLint.Options = {
cwd: project.location,
errorOnUnmatchedPattern: false,
ignorePath: path.join(project.location, '.config/eslintignore'),
Expand All @@ -71,12 +74,28 @@ export async function fixFunction() {
),
useEslintrc: false,
fix: true,
cache: false,
// cacheLocation: path.join(
// project.location,
// '.config/.cache/eslintcache',
// ),
})
cache: false

}
const cacheLocation = path.join(
project.location,
'.config/.cache/eslintcache',
)
if(project.foxConfig.cache === true) {
eslintObj.cache = true,
eslintObj.cacheLocation
} else {
// ensure eslint cache is removed
try {
await fs.promises.unlink(cacheLocation)
} catch (err) {
if (err.code !== "ENOENT") {
log.error('problem removing eslint cache')
console.error(err);
}
}
}
const eslint = new ESLint(eslintObj)

// const tsEslint = new ESLint({
// cwd: project.location,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
*/
export default function(fox) {
return {
// your overrides
rules: {
'no-undef': 'off'

}
}
}
1 change: 1 addition & 0 deletions packages/fox-plugin-prettier/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export async function fixFunction(): Promise<void> {
log.error('default export is not a function. skipping prettier')
return
}

const userConfig = userConfigModule.default(project.foxConfig)

const mergedConfig = Object.assign({}, defaultConfig, userConfig)
Expand Down
1 change: 1 addition & 0 deletions packages/fox-suite/src/types/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// TODO: export types by fox-types to be accessable by /** @type {import("fox-types/types").IFoxConfig} */
64 changes: 61 additions & 3 deletions packages/fox-types/types.d.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,83 @@
import { PackageJson } from 'type-fest'
import type { Stats } from 'fs'
type option = 'off' | 'cozy' | 'strict' | 'excessive'


/**
* @description format of the `fox.config.js` file
*/
export interface IFoxConfig {
all: option
/**
* @description changes the lint behavior of all linters
* (plugins that have a `fixFunction` method)
*/
all: 'off' | 'cozy' | 'strict' | 'excessive'

/**
* @description set to true if `fox.config.js` is at the
* root of a monorepo (at the same level as `lerna.json`,
* `pnpm-workspace.yaml`, etc.)
*/
monorepo: boolean

/**
* @description set to true to enable caching. caching functionality
* is a plugin dependent feature; some may not have it. once set to false,
* existing caches are removed (for the plugins selected to run)
* @todo make this automatically false for CI
*/
cache: boolean

/**
* @deprecated
* @description array containing current environments
* @todo deprecate. this is only useful for javascript, and we can include
* quick commented out good defaults for eslint env property
*/
env: [ 'browser' ] | [ 'node' ] | [ 'deno' ] | ['browser', 'node' ]
| ['browser', 'deno'] | ['node', 'deno'] | ['browser', 'deno', 'node'] | []
plugins: Record<string, option>

/**
* @description object containing an entry for each plugin,
* to change its linting severity. same options as the 'all' property
* @example
* ```js
* // if `fox-plugin-stylelint` is installed,
* // we can do the following
* plugins: {
* stylelint: 'strict'
* }
* ```
*/
plugins: Record<string, 'off' | 'cozy' | 'strict' | 'excessive'>
}

/**
* @description used when building a cli
*/
export interface IBuildCli {
/**
* @description the name of your plugin. recommended this
* be the same as in your `info.ts` file
*/
pluginName: string

/**
* @description a description of what your plugin does.
* recommended this be the same as in your `info.ts` file`
*/
pluginDescription: string

/**
* @description this should be the same function exported
* from your `index.ts` file
*/
bootstrapFunction?: () => Promise<void>

/**
* @description this should be the same function exported
* from your `index.ts` file
* @todo make this optional
*/
fixFunction: (fox: IFoxConfig) => Promise<void>
}

Expand Down
3 changes: 2 additions & 1 deletion packages/fox-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,14 @@
"typescript": "^3.9.5"
},
"dependencies": {
"minimist": "^1.2.5",
"colorette": "^1.2.0",
"debug": "^4.1.1",
"esm": "^3.2.25",
"glob": "^7.1.6",
"lodash.merge": "^4.6.2",
"lodash.mergewith": "^4.6.2",
"minimist": "^1.2.5",
"mkdirp": "^1.0.4",
"pkg-up": "^3.1.0",
"prompts": "^2.3.2",
"read-pkg-up": "^7.0.1"
Expand Down
35 changes: 26 additions & 9 deletions packages/fox-utils/src/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@ import { getPluginData } from './plugin.js'
import debug from './debug'
import merge from 'lodash.merge'
import { log } from './misc'
import mkdirp from 'mkdirp'

/**
* generate boilerpalte configuration in `.config`
* folder of local projet
*/

/**
* @description do handlebars template
*/
async function doHandlebarsTemplate(
fileContents: string,
{ pluginData, projectData }: { pluginData: IPlugin; projectData: IProject },
Expand All @@ -40,6 +44,7 @@ export async function buildBootstrap(opts: IBuildBootstrap): Promise<void> {
getPluginData(opts.dirname),
getProjectData(),
])

const doTemplate = async (
fileToTemplate: ITemplateFile,
): Promise<{ fileDest: string; templatedText: string }> => {
Expand All @@ -64,17 +69,29 @@ export async function buildBootstrap(opts: IBuildBootstrap): Promise<void> {

const retryFilesToTemplate: ITemplateFile[] = []
for (const fileToTemplate of pluginData.templateFiles) {
debug(`trying to copy file '${fileToTemplate.absolutePath}' over`)
const { fileDest, templatedText } = await doTemplate(fileToTemplate)

try {
try {
await fs.promises.mkdir(path.dirname(fileDest), {
mode: 0o755,
})
} catch {}
await fs.promises.writeFile(fileDest, templatedText, {
mode: 0o644,
flag: 'wx+',
})
// ensure parent directory exists
await mkdirp(path.dirname(fileDest), {
mode: 0o755,
});

const destinationText = await fs.promises.readFile(fileDest, { encoding: 'utf8' })

// if content is the same, don't actually try
// and overwrite the file
debug(`is destinationText same as templatedText?: ${destinationText === templatedText}`);
if (destinationText === templatedText) {
log.info(`skipping ${fileToTemplate.relativePath} since contents are the same`);
} else {
await fs.promises.writeFile(fileDest, templatedText, {
mode: 0o644,
flag: "wx+",
});
}

} catch (err) {
if (err.code === 'EEXIST') {
// if the file already exists, but is a json file,
Expand Down
54 changes: 54 additions & 0 deletions packages/fox-utils/src/fix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { getPluginData } from './plugin'
import path from 'path'
import fs from 'fs'
import { log } from './misc'
import merge from 'lodash.merge'

export async function buildFix(opts: IBuildFix): Promise<void> {
const [projectData, pluginData] = await Promise.all([
Expand Down Expand Up @@ -54,3 +55,56 @@ export async function buildFix(opts: IBuildFix): Promise<void> {
log.info(`running ${info.name} fix`)
await opts.fn()
}

const parseIgnoreFile = async (ignoreFilePath: string): Promise<string[]> => {
const content = await fs.promises.readFile(ignoreFilePath, { encoding: 'utf8' })
return []
}

interface IGetConfigAndIgnores {
defaultConfig: Record<string, any>,
userConfigPath: string,
configMergeFn?: (defaultConfig: Record<string, any>, userConfig: Record<string, any>) => Record<string, any>
ignoreFilePath?: string
}

export async function getConfigAndIgnores({
defaultConfig,
userConfigPath,
configMergeFn,
ignoreFilePath,
}: IGetConfigAndIgnores): Promise<{
mergedConfig: Record<string, any> | null,
ignoredFiles?: string[] | null
}> {
const project = await getProjectData()

const userConfigModule = (await import(userConfigPath))
if (typeof userConfigModule.default !== 'function') {
log.error('default export is not a function. skipping eslint')
return {
mergedConfig: null,
ignoredFiles: null
}
}

const userConfig = userConfigModule.default(project.foxConfig)

let ignoredFiles = null
if (ignoreFilePath) {
ignoredFiles = await parseIgnoreFile(ignoreFilePath)
}

if (!configMergeFn) {
return {
mergedConfig: merge(defaultConfig, userConfig),
ignoredFiles,
}
} else {
return {
mergedConfig: configMergeFn(defaultConfig, userConfig),
ignoredFiles,
}
}

}
1 change: 1 addition & 0 deletions packages/fox-utils/src/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export async function getProjectData(): Promise<IProject> {
// default foxConfig options
const defaultFoxConfig: IFoxConfig = {
all: 'cozy',
cache: false,
monorepo: false,
env: [],
plugins: {}
Expand Down
Loading

0 comments on commit 67da875

Please sign in to comment.