mirror of
https://github.com/chirimen-oh/node-web-gpio.git
synced 2025-01-18 08:05:07 +00:00
husky, lint-staged, prettier 導入によるコミット時の自動フォーマット (#29)
* cf feature/prettier husky, lint-staged, prettier add.
This commit is contained in:
parent
2e74629f0c
commit
13b064f140
8 changed files with 698 additions and 376 deletions
24
.eslintrc.js
24
.eslintrc.js
|
@ -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
24
.eslintrc.yml
Normal 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
7
.husky/pre-commit
Executable 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
7
.lintstagedrc.yaml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
"*.ts":
|
||||||
|
# typescript
|
||||||
|
# prettier で、ダブルクオートからシングルクオートへ
|
||||||
|
- prettier --write --single-quote
|
||||||
|
"*.{md,yml}":
|
||||||
|
# markdown, yaml
|
||||||
|
- prettier --write
|
66
index.ts
66
index.ts
|
@ -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,26 +139,26 @@ 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 {
|
||||||
throw new OperationError(error);
|
throw new OperationError(error);
|
||||||
|
@ -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),
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -258,4 +258,4 @@ function sleep(ms: number) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
return setTimeout(resolve, ms);
|
return setTimeout(resolve, ms);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
14
package.json
14
package.json
|
@ -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",
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
{
|
|
||||||
"extends": "./tsconfig.json",
|
|
||||||
"include": [
|
|
||||||
"*.ts",
|
|
||||||
".eslintrc.js"
|
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"node_modules",
|
|
||||||
"dist"
|
|
||||||
]
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue