Skip to content

Commit

Permalink
feat: big improvements and initialization capabilities
Browse files Browse the repository at this point in the history
  • Loading branch information
spence-s committed Mar 27, 2022
1 parent 01bb434 commit 2d76530
Show file tree
Hide file tree
Showing 18 changed files with 1,172 additions and 688 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ coverage
*.log

test/temp

t

This comment has been minimized.

Copy link
@titanism

titanism Mar 28, 2022

@spence-s extra t?

This comment has been minimized.

Copy link
@spence-s

spence-s Mar 28, 2022

Author Member

on purpose for testing :)

30 changes: 16 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,32 +26,35 @@
],
"dependencies": {
"cosmiconfig": "^7.0.1",
"debug": "^4.3.3",
"execa": "^6.0.0",
"fs-extra": "^10.0.0",
"debug": "^4.3.4",
"execa": "^6.1.0",
"fs-extra": "^10.0.1",
"is-string-and-not-blank": "^0.0.2",
"load-json-file": "^7.0.1",
"lodash": "^4.17.21",
"meow": "^10.1.2",
"npm-check-updates": "^12.0.5",
"ora": "^6.0.1",
"npm-check-updates": "^12.5.4",
"npm-conf": "^1.1.3",
"ora": "^6.1.0",
"path-exists": "^5.0.0",
"prompts": "^2.4.2",
"read-pkg-up": "^9.0.0",
"tmp-promise": "^3.0.3"
"read-pkg-up": "^9.1.0",
"superb": "^4.0.0",
"tmp-promise": "^3.0.3",
"validate-npm-package-name": "^3.0.0"
},
"devDependencies": {
"@commitlint/cli": "^15.0.0",
"@commitlint/config-conventional": "^15.0.0",
"ava": "^4.0.0-rc.1",
"@commitlint/cli": "^16.2.3",
"@commitlint/config-conventional": "^16.2.1",
"ava": "^4.1.0",
"codecov": "^3.8.2",
"cross-env": "latest",
"fixpack": "^4.0.0",
"husky": "^7.0.4",
"lint-staged": "^12.1.3",
"lint-staged": "^12.3.7",
"nyc": "^15.1.0",
"sinon": "^12.0.1",
"xo": "^0.47.0"
"sinon": "^13.0.1",
"xo": "^0.48.0"
},
"engines": {
"node": ">= 12"
Expand All @@ -73,7 +76,6 @@
"lint:js": "xo",
"lint:md": "prettier --check **/*.md",
"lint:package": "fixpack --dryrun",
"pretest": "yarn run lint",
"test": "cross-env NODE_ENV=test ava",
"test-coverage": "cross-env NODE_ENV=test nyc yarn run test"
},
Expand Down
5 changes: 3 additions & 2 deletions src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ const cli = meow(
Examples
$ lassify
$ lassify --cwd '../other/directory'
$ lassify --silent
$ lassify -y
`,
{
importMeta: import.meta,
Expand All @@ -40,8 +42,7 @@ const cli = meow(
try {
await new Lassify(cli.flags).run();
process.exit(0);
} catch (error) {
console.error(error);
} catch {
process.exit(1);
}
})();
4 changes: 3 additions & 1 deletion src/helpers/config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// currently not used
export const MANAGED_DEPS = [
'husky',
'xo',
Expand All @@ -24,5 +25,6 @@ export const configMap = {
husky: 'husky',
commitlint: ['@commitlint/cli', '@commitlint/config-conventional'],
xo: 'xo',
lintStaged: 'lint-staged'
lintStaged: 'lint-staged',
ava: 'ava'
};
5 changes: 3 additions & 2 deletions src/helpers/ora-debug-redirect.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ function oraDebugRedirect(oraOptions) {
const fakeOra = {};
const oraLogger = debugLogger.extend('ora');
if (debugLogger.enabled) {
for (const method of ['start', 'stop', 'warn', 'succeed', 'fail']) {
fakeOra[method] = oraLogger;
for (const method of ['start', 'stop', 'warn', 'succeed', 'fail', 'info']) {
fakeOra[method] = (...args) =>
args.length > 0 ? oraLogger(...args) : null;
}

return fakeOra;
Expand Down
2 changes: 1 addition & 1 deletion src/helpers/write-package-file.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import prettier from 'prettier';
async function writePackageFile() {
const prettierConfig =
(await prettier.resolveConfig(this.pkgPath, {
eidtorConfig: true,
editorConfig: true,
useCache: false
})) || {};

Expand Down
27 changes: 20 additions & 7 deletions src/lassify.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import process from 'node:process';
import { resolve } from 'node:path';
import { execa } from 'execa';
import debug from 'debug';

Expand All @@ -7,6 +8,9 @@ import manageGitInit from './modules/git-init.js';
import manageGitIgnore from './modules/git-ignore.js';
import manageDeps from './modules/dependencies.js';
import manageLintStaged from './modules/lint-staged.js';
import manageEditorConfig from './modules/editor-config.js';
import managePkg from './modules/pkg.js';

import manageHusky from './modules/husky.js';

import ora from './helpers/ora-debug-redirect.js';
Expand All @@ -16,7 +20,8 @@ import { configMap, defaultConfig } from './helpers/config.js';
class Lassify {
constructor(options) {
this.debug = debug('lassify');
this.cwd = options.cwd ?? process.cwd();
this.cwd = options.cwd ? resolve(options.cwd) : process.cwd();
this.debug(`cwd: ${this.cwd}`);
this.yes = options.yes || false;
this.configPath = options.config;

Expand All @@ -34,6 +39,8 @@ class Lassify {
this.initialize = initialize.bind(this);
this.manageGitInit = manageGitInit.bind(this);
this.manageGitIgnore = manageGitIgnore.bind(this);
this.editorConfig = manageEditorConfig.bind(this);
this.managePkg = managePkg.bind(this);
this.manageDeps = manageDeps.bind(this);
this.manageLintStaged = manageLintStaged.bind(this);
this.manageHusky = manageHusky.bind(this);
Expand All @@ -45,12 +52,18 @@ class Lassify {
* may set variables for use by later functions
*/
async run() {
await this.initialize();
await this.manageGitInit();
await this.manageGitIgnore();
await this.manageDeps();
await this.manageHusky();
await this.manageLintStaged();
try {
await this.initialize();
await this.managePkg();
await this.manageGitInit();
await this.editorConfig();
await this.manageGitIgnore();
await this.manageDeps();
await this.manageHusky();
await this.manageLintStaged();
} catch (error) {
this.spinner.fail(error.message);
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/modules/dependencies.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ async function manageDependencies() {
.filter(Boolean);

spinner.stop();
debug('questions answered');

if (this.yes) prompts.inject(questions.map(() => true));

Expand Down Expand Up @@ -97,7 +98,7 @@ async function manageDependencies() {
spinner.succeed(
'Installing new and/or updated dependencies selected dependencies'
);
await this.spawn('yarn', ['install']);
await this.spawn(this.pm, ['install']);
spinner.stop();

spinner.succeed('Dependencies installed!');
Expand Down
65 changes: 65 additions & 0 deletions src/modules/editor-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import path from 'node:path';
import fs from 'fs-extra';
import { pathExists } from 'path-exists';

async function gitIgnore() {
const debug = this.debug.extend('editor-config');
const { spinner } = this;
const editorconfigPath = path.join(this.cwd, '.editorconfig');
const defaultEditorConfig = [
'root = true',
'',
'[*]',
'indent_style = space',
'indent_size = 2',
'end_of_line = lf',
'charset = utf-8',
'trim_trailing_whitespace = true',
'insert_final_newline = true'
];

debug('checking if .editorconfig exists in %s', this.cwd);
if (await pathExists(editorconfigPath)) {
spinner.warn('A custom .editorconfig has already been created.');

// merge in our ignore
const currentGitIgnore = [
...(await fs.readFile(editorconfigPath))
// eslint-disable-next-line unicorn/no-await-expression-member
.toString()
.split('\n')

.map((line) => line.trim()),
''
];

let isChanged = false;

// simple dedupe
for (const ignore of defaultEditorConfig.filter(
(line) => !line.startsWith('#')
)) {
if (currentGitIgnore.includes(ignore)) continue;
currentGitIgnore.push(ignore);
isChanged = true;
}

currentGitIgnore.push('');

if (isChanged) {
await fs.writeFile(defaultEditorConfig, currentGitIgnore.join('\n'));
spinner.succeed('Fixed .editorconfig!');
} else {
spinner.warn('No .editorconfig changes needed');
}
} else {
spinner.start('Creating new .editorconfig');
await fs.writeFile(
path.join(this.cwd, '.editorconfig'),
defaultEditorConfig.join('\n')
);
spinner.succeed('.editorconfig created');
}
}

export default gitIgnore;
7 changes: 3 additions & 4 deletions src/modules/git-ignore.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,12 @@ async function gitIgnore() {
spinner.warn('A custom .gitignore has already been created.');

// merge in our ignore
const currentGitIgnore = await [
...(
await fs.readFile(gitIgnorePath)
)
const currentGitIgnore = [
...(await fs.readFile(gitIgnorePath))
// eslint-disable-next-line unicorn/no-await-expression-member
.toString()
.split('\n')

.map((line) => line.trim()),
''
];
Expand Down
11 changes: 7 additions & 4 deletions src/modules/husky.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ async function manageHusky() {
debug('checking for husky upgrade path if needed.');

let huskyUpgradePath;
if (semver.subset(this.originalDependencies.husky, '0'))
if (semver.subset(this.originalDependencies?.husky ?? '', '0'))
huskyUpgradePath = '0';
else if (semver.subset(this.originalDependencies.husky, '1 - 4'))
else if (semver.subset(this.originalDependencies?.husky ?? '', '1 - 4'))
huskyUpgradePath = '1';

if (huskyUpgradePath) {
Expand Down Expand Up @@ -112,7 +112,9 @@ async function manageHusky() {
await husky([
'add',
`.husky/${hook}`,
`${this.pm} ${command.replace('HUSKY_GIT_PARAMS', '$1')}`
`${this.pm} ${command
.replace('HUSKY_GIT_PARAMS', '$1')
.replace('-E', '--edit')}`
]);

spinner.succeed();
Expand All @@ -125,7 +127,8 @@ async function manageHusky() {
this.writePackageJson();
}
}
} else if (this.config?.git?.commitlint) {
} else if (this.config.commitlint) {
debug('install commitlint husky hook');
// install commitlint husky hook
if (await pathExists(path.join(this.cwd, '.husky', 'commit-msg'))) {
spinner.warn('There is already a commit-msg hook installed for husky');
Expand Down
44 changes: 31 additions & 13 deletions src/modules/initialize.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import ncu from 'npm-check-updates';
import { pathExists } from 'path-exists';
import * as _ from '../helpers/_.js';

/**
* Finds or creates the package.json for the current working dir.
* @returns this
*/
async function initialize() {
const debug = this.debug.extend('init');
this.spinner.start('Initializing lassify!');
Expand All @@ -15,14 +19,18 @@ async function initialize() {
if (this.configPath) {
const config = await loadJsonFile(this.configPath);
this.config = Object.freeze(config);
debug('found passed config');
} else {
const { config = this.config, filepath: configPath } = (await cosmiconfig(
'lass'
).search(this.cwd)) || {
config: this.defaultConfig
};
debug('searching for config');
const { config = this.config, filepath: configPath } =
(await cosmiconfig('lass').search(this.cwd)) ||
(() => {
debug('using default config');
return { config: this.defaultConfig };
})();
this.configPath = configPath;
this.config = Object.freeze(config);
debug('config resolved');
}

// all the dependencies we should take care of
Expand All @@ -39,20 +47,23 @@ async function initialize() {
'Configuration must have at least 1 dependency for lassify to manage'
);

debug('found and cached config');
debug('cached config');

// find the package.json - must be in this dir
const { path: pkgPath, packageJson } = await readPackageUp({
const { path: pkgPath, packageJson } = (await readPackageUp({
cwd: this.cwd,
normalize: false
});
normalize: false,
stopAt: this.cwd
})) || { path: path.join(this.cwd, 'package.json'), packageJson: {} };

if (path.dirname(pkgPath) !== this.cwd)
throw new Error('Run lassify in a directory with a package.json');
debug('package %O', packageJson);

let shouldSavePackage = false;
if (_.isEmpty(packageJson)) shouldSavePackage = true;

// cache the original package.json as well as some extra meta stuff we can use later
this.packageJson = { ...packageJson };
this.originalPackageJson = Object.freeze(packageJson);
this.packageJson = packageJson;
this.pkgPath = pkgPath;

debug('found and cached packageJson for %s', pkgPath);
Expand Down Expand Up @@ -91,10 +102,17 @@ async function initialize() {
// const figure out package manager
this.pm = (await pathExists(path.join(this.cwd, 'yarn.lock')))
? 'yarn'
: 'npx';
: (await pathExists(path.join(this.cwd, 'package-lock.json')))
? 'npm'
: '';

this.spinner.succeed('Lassify initialized successfully!');

if (shouldSavePackage) {
debug('saving package.json because we are in a directory without one.');
await this.writePackageJson();
}

return this;
}

Expand Down
Loading

0 comments on commit 2d76530

Please sign in to comment.