husky, lint-staged, prettier 導入によるコミット時の自動フォーマット (#29)

* cf feature/prettier husky, lint-staged, prettier add.
This commit is contained in:
Akihiko.KIgure 2021-12-08 10:01:04 +09:00 committed by GitHub
parent 2e74629f0c
commit 13b064f140
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 698 additions and 376 deletions

View file

@ -1,24 +0,0 @@
module.exports = {
root: true,
env: {
es6: true,
node: true,
},
parser: '@typescript-eslint/parser',
parserOptions: {
sourceType: 'module',
ecmaVersion: 2019, // Node.js 12の場合は2019、他のバージョンのNode.jsを利用している場合は場合は適宜変更する
tsconfigRootDir: __dirname,
project: ['./tsconfig.eslint.json']
},
plugins: [
'@typescript-eslint',
],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking',
],
rules: {
},
};

24
.eslintrc.yml Normal file
View file

@ -0,0 +1,24 @@
env:
node: true
es6: true
parser: "@typescript-eslint/parser"
parserOptions:
sourceType: "module"
ecmaVersion: 2019 # Node.js 12の場合は2019、他のバージョンのNode.jsを利用している場合は場合は適宜変更する
project: ./tsconfig.json
plugins:
- "@typescript-eslint"
ignorePatterns:
# 除外対象
- ./node_modules
- ./dist
extends:
- "eslint:recommended"
- "plugin:@typescript-eslint/recommended"
- "plugin:@typescript-eslint/recommended-requiring-type-checking"
rules: {
# 暫定処置 この記述がないとlint が通らない
# この対応は、別issue
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/no-unsafe-argument": 0,
}

7
.husky/pre-commit Executable file
View file

@ -0,0 +1,7 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# eslint 実行
npm run lint
# lint-staged 実行prettier
npm run precommit

7
.lintstagedrc.yaml Normal file
View file

@ -0,0 +1,7 @@
"*.ts":
# typescript
# prettier で、ダブルクオートからシングルクオートへ
- prettier --write --single-quote
"*.{md,yml}":
# markdown, yaml
- prettier --write

View file

@ -1,13 +1,13 @@
import { EventEmitter } from "events"; import { EventEmitter } from 'events';
import { promises as fs } from "fs"; import { promises as fs } from 'fs';
import * as path from "path"; import * as path from 'path';
/** /**
* Interval of file system polling, in milliseconds. * Interval of file system polling, in milliseconds.
*/ */
const PollingInterval = 100; const PollingInterval = 100;
const SysfsGPIOPath = "/sys/class/gpio"; const SysfsGPIOPath = '/sys/class/gpio';
const GPIOPortMapSizeMax = 1024; const GPIOPortMapSizeMax = 1024;
@ -23,7 +23,7 @@ type PortNumber = number;
type PortName = string; type PortName = string;
type PinName = string; type PinName = string;
type DirectionMode = "in" | "out"; type DirectionMode = 'in' | 'out';
type GPIOValue = 0 | 1; type GPIOValue = 0 | 1;
@ -44,13 +44,13 @@ export class GPIOAccess extends EventEmitter {
super(); super();
this._ports = ports == null ? new GPIOPortMap() : ports; this._ports = ports == null ? new GPIOPortMap() : ports;
this._ports.forEach(port => this._ports.forEach((port) =>
port.on("change", event => { port.on('change', (event) => {
this.emit("change", event); this.emit('change', event);
}) })
); );
this.on("change", (event: GPIOChangeEvent): void => { this.on('change', (event: GPIOChangeEvent): void => {
if (this.onchange !== undefined) this.onchange(event); if (this.onchange !== undefined) this.onchange(event);
}); });
} }
@ -64,7 +64,7 @@ export class GPIOAccess extends EventEmitter {
*/ */
async unexportAll(): Promise<void> { async unexportAll(): Promise<void> {
await Promise.all( await Promise.all(
[...this.ports.values()].map(port => [...this.ports.values()].map((port) =>
port.exported ? port.unexport() : undefined port.exported ? port.unexport() : undefined
) )
); );
@ -91,11 +91,11 @@ export class GPIOPort extends EventEmitter {
this._portNumber = parseUint16(portNumber.toString()); this._portNumber = parseUint16(portNumber.toString());
this._pollingInterval = PollingInterval; this._pollingInterval = PollingInterval;
this._direction = new OperationError("Unknown direction."); this._direction = new OperationError('Unknown direction.');
this._exported = new OperationError("Unknown export."); this._exported = new OperationError('Unknown export.');
this._exportRetry = 0; this._exportRetry = 0;
this.on("change", (event: GPIOChangeEvent): void => { this.on('change', (event: GPIOChangeEvent): void => {
if (this.onchange !== undefined) this.onchange(event); if (this.onchange !== undefined) this.onchange(event);
}); });
} }
@ -110,7 +110,7 @@ export class GPIOPort extends EventEmitter {
get pinName(): PinName { get pinName(): PinName {
// NOTE: Unknown pinName. // NOTE: Unknown pinName.
return ""; return '';
} }
get direction(): DirectionMode { get direction(): DirectionMode {
@ -139,25 +139,25 @@ export class GPIOPort extends EventEmitter {
clearInterval(this._timeout as ReturnType<typeof setInterval>); clearInterval(this._timeout as ReturnType<typeof setInterval>);
if (!this.exported) { if (!this.exported) {
await fs.writeFile( await fs.writeFile(
path.join(SysfsGPIOPath, "export"), path.join(SysfsGPIOPath, 'export'),
String(this.portNumber) String(this.portNumber)
); );
} }
await fs.writeFile( await fs.writeFile(
path.join(SysfsGPIOPath, this.portName, "direction"), path.join(SysfsGPIOPath, this.portName, 'direction'),
direction direction
); );
if (direction === "in") { if (direction === 'in') {
this._timeout = setInterval( this._timeout = setInterval(
// eslint-disable-next-line // eslint-disable-next-line
this.read.bind(this), this.read.bind(this),
this._pollingInterval this._pollingInterval
); );
} }
} catch (error) { } catch (error: any) {
if (this._exportRetry == 0) { if (this._exportRetry == 0) {
await sleep(100); await sleep(100);
console.warn("May be the first time port access. Retry.."); console.warn('May be the first time port access. Retry..');
++this._exportRetry; ++this._exportRetry;
await this.export(direction); await this.export(direction);
} else { } else {
@ -174,10 +174,10 @@ export class GPIOPort extends EventEmitter {
try { try {
await fs.writeFile( await fs.writeFile(
path.join(SysfsGPIOPath, "unexport"), path.join(SysfsGPIOPath, 'unexport'),
String(this.portNumber) String(this.portNumber)
); );
} catch (error) { } catch (error: any) {
throw new OperationError(error); throw new OperationError(error);
} }
@ -185,7 +185,7 @@ export class GPIOPort extends EventEmitter {
} }
async read(): Promise<GPIOValue> { async read(): Promise<GPIOValue> {
if (!(this.exported && this.direction === "in")) { if (!(this.exported && this.direction === 'in')) {
throw new InvalidAccessError( throw new InvalidAccessError(
`The exported must be true and value of direction must be "in".` `The exported must be true and value of direction must be "in".`
); );
@ -193,24 +193,24 @@ export class GPIOPort extends EventEmitter {
try { try {
const buffer = await fs.readFile( const buffer = await fs.readFile(
path.join(SysfsGPIOPath, this.portName, "value") path.join(SysfsGPIOPath, this.portName, 'value')
); );
const value = parseUint16(buffer.toString()) as GPIOValue; const value = parseUint16(buffer.toString()) as GPIOValue;
if (this._value !== value) { if (this._value !== value) {
this._value = value; this._value = value;
this.emit("change", { value, port: this }); this.emit('change', { value, port: this });
} }
return value; return value;
} catch (error) { } catch (error: any) {
throw new OperationError(error); throw new OperationError(error);
} }
} }
async write(value: GPIOValue): Promise<void> { async write(value: GPIOValue): Promise<void> {
if (!(this.exported && this.direction === "out")) { if (!(this.exported && this.direction === 'out')) {
throw new InvalidAccessError( throw new InvalidAccessError(
`The exported must be true and value of direction must be "out".` `The exported must be true and value of direction must be "out".`
); );
@ -218,10 +218,10 @@ export class GPIOPort extends EventEmitter {
try { try {
await fs.writeFile( await fs.writeFile(
path.join(SysfsGPIOPath, this.portName, "value"), path.join(SysfsGPIOPath, this.portName, 'value'),
parseUint16(value.toString()).toString() parseUint16(value.toString()).toString()
); );
} catch (error) { } catch (error: any) {
throw new OperationError(error); throw new OperationError(error);
} }
} }
@ -245,9 +245,9 @@ export class OperationError extends Error {
// eslint-disable-next-line // eslint-disable-next-line
export async function requestGPIOAccess(): Promise<GPIOAccess> { export async function requestGPIOAccess(): Promise<GPIOAccess> {
const ports = new GPIOPortMap( const ports = new GPIOPortMap(
[...Array(GPIOPortMapSizeMax).keys()].map(portNumber => [ [...Array(GPIOPortMapSizeMax).keys()].map((portNumber) => [
portNumber, portNumber,
new GPIOPort(portNumber) new GPIOPort(portNumber),
]) ])
); );

View file

@ -14,16 +14,20 @@
"author": "Kohei Watanabe <kou029w@gmail.com>", "author": "Kohei Watanabe <kou029w@gmail.com>",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@types/node": "^16.0.0", "@types/node": "^16.11.11",
"@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/eslint-plugin": "^5.5.0",
"@typescript-eslint/parser": "^5.0.0", "@typescript-eslint/parser": "^5.5.0",
"eslint": "^8.0.0", "eslint": "^8.4.0",
"husky": "^7.0.4",
"lint-staged": "^12.1.2",
"prettier": "^2.5.1",
"typescript": "^4.2.3" "typescript": "^4.2.3"
}, },
"scripts": { "scripts": {
"build": "tsc", "build": "tsc",
"lint": "eslint index.ts", "lint": "eslint index.ts",
"prepare": "rm -rf dist && npm run build" "prepare": "husky install && rm -rf dist && npm run build",
"precommit": "lint-staged"
}, },
"keywords": [ "keywords": [
"gpio", "gpio",

View file

@ -1,11 +0,0 @@
{
"extends": "./tsconfig.json",
"include": [
"*.ts",
".eslintrc.js"
],
"exclude": [
"node_modules",
"dist"
]
}

921
yarn.lock

File diff suppressed because it is too large Load diff