refactor(misskey-games): Misskey Games系パッケージのlint修正+Lint CI整備 (#14612)

* chore(lint): Fix linting in misskey-reversi

(cherry picked from commit 894934a1a7743472b2d051e2690007ae373efd76)

* chore(lint): Fix linting in misskey-bubble-game

(cherry picked from commit 1ba9c37a8d5e4ae6a98494026b87f6f6439790c7)

* enhance(gh): add lint ci for misskey games packages

* enhance(gh): fix lint ci

* fix

* revert some changes that nothing to do with lint rules

* fix

* lint fixes

* refactor: strict type def

* lint fixes

* 🎨

* 🎨

---------

Co-authored-by: 4censord <mail@4censord.de>
This commit is contained in:
かっこかり 2024-09-23 21:25:23 +09:00 committed by GitHub
parent 733fd56058
commit 7f7445ad7a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 68 additions and 45 deletions

View file

@ -12,6 +12,8 @@ on:
- packages/frontend-embed/** - packages/frontend-embed/**
- packages/sw/** - packages/sw/**
- packages/misskey-js/** - packages/misskey-js/**
- packages/misskey-bubble-game/**
- packages/misskey-reversi/**
- packages/shared/eslint.config.js - packages/shared/eslint.config.js
- .github/workflows/lint.yml - .github/workflows/lint.yml
pull_request: pull_request:
@ -22,6 +24,8 @@ on:
- packages/frontend-embed/** - packages/frontend-embed/**
- packages/sw/** - packages/sw/**
- packages/misskey-js/** - packages/misskey-js/**
- packages/misskey-bubble-game/**
- packages/misskey-reversi/**
- packages/shared/eslint.config.js - packages/shared/eslint.config.js
- .github/workflows/lint.yml - .github/workflows/lint.yml
jobs: jobs:
@ -53,6 +57,8 @@ jobs:
- frontend-embed - frontend-embed
- sw - sw
- misskey-js - misskey-js
- misskey-bubble-game
- misskey-reversi
env: env:
eslint-cache-version: v1 eslint-cache-version: v1
eslint-cache-path: ${{ github.workspace }}/node_modules/.cache/eslint-${{ matrix.workspace }} eslint-cache-path: ${{ github.workspace }}/node_modules/.cache/eslint-${{ matrix.workspace }}

View file

@ -1,32 +1,32 @@
import * as esbuild from "esbuild"; import fs from 'node:fs';
import { build } from "esbuild"; import { fileURLToPath } from 'node:url';
import { globSync } from "glob"; import { dirname } from 'node:path';
import { execa } from "execa"; import * as esbuild from 'esbuild';
import fs from "node:fs"; import { build } from 'esbuild';
import { fileURLToPath } from "node:url"; import { globSync } from 'glob';
import { dirname } from "node:path"; import { execa } from 'execa';
const _filename = fileURLToPath(import.meta.url); const _filename = fileURLToPath(import.meta.url);
const _dirname = dirname(_filename); const _dirname = dirname(_filename);
const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8')); const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8'));
const entryPoints = globSync("./src/**/**.{ts,tsx}"); const entryPoints = globSync('./src/**/**.{ts,tsx}');
/** @type {import('esbuild').BuildOptions} */ /** @type {import('esbuild').BuildOptions} */
const options = { const options = {
entryPoints, entryPoints,
minify: process.env.NODE_ENV === 'production', minify: process.env.NODE_ENV === 'production',
outdir: "./built", outdir: './built',
target: "es2022", target: 'es2022',
platform: "browser", platform: 'browser',
format: "esm", format: 'esm',
sourcemap: 'linked', sourcemap: 'linked',
}; };
// built配下をすべて削除する // built配下をすべて削除する
fs.rmSync('./built', { recursive: true, force: true }); fs.rmSync('./built', { recursive: true, force: true });
if (process.argv.map(arg => arg.toLowerCase()).includes("--watch")) { if (process.argv.map(arg => arg.toLowerCase()).includes('--watch')) {
await watchSrc(); await watchSrc();
} else { } else {
await buildSrc(); await buildSrc();
@ -36,7 +36,7 @@ async function buildSrc() {
console.log(`[${_package.name}] start building...`); console.log(`[${_package.name}] start building...`);
await build(options) await build(options)
.then(it => { .then(() => {
console.log(`[${_package.name}] build succeeded.`); console.log(`[${_package.name}] build succeeded.`);
}) })
.catch((err) => { .catch((err) => {
@ -65,7 +65,7 @@ function buildDts() {
{ {
stdout: process.stdout, stdout: process.stdout,
stderr: process.stderr, stderr: process.stderr,
} },
); );
} }
@ -86,7 +86,7 @@ async function watchSrc() {
}, },
}]; }];
console.log(`[${_package.name}] start watching...`) console.log(`[${_package.name}] start watching...`);
const context = await esbuild.context({ ...options, plugins }); const context = await esbuild.context({ ...options, plugins });
await context.watch(); await context.watch();

View file

@ -1,6 +1,7 @@
import tsParser from '@typescript-eslint/parser'; import tsParser from '@typescript-eslint/parser';
import sharedConfig from '../shared/eslint.config.js'; import sharedConfig from '../shared/eslint.config.js';
// eslint-disable-next-line import/no-default-export
export default [ export default [
...sharedConfig, ...sharedConfig,
{ {

View file

@ -199,13 +199,12 @@ export class DropAndFusionGame extends EventEmitter<{
}; };
if (mono.shape === 'circle') { if (mono.shape === 'circle') {
return Matter.Bodies.circle(x, y, mono.sizeX / 2, options); return Matter.Bodies.circle(x, y, mono.sizeX / 2, options);
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
} else if (mono.shape === 'rectangle') { } else if (mono.shape === 'rectangle') {
return Matter.Bodies.rectangle(x, y, mono.sizeX, mono.sizeY, options); return Matter.Bodies.rectangle(x, y, mono.sizeX, mono.sizeY, options);
} else if (mono.shape === 'custom') { } else if (mono.shape === 'custom' && mono.vertices != null && mono.verticesSize != null) { //eslint-disable-line @typescript-eslint/no-unnecessary-condition
return Matter.Bodies.fromVertices(x, y, mono.vertices!.map(i => i.map(j => ({ return Matter.Bodies.fromVertices(x, y, mono.vertices.map(i => i.map(j => ({
x: (j.x / mono.verticesSize!) * mono.sizeX, x: (j.x / mono.verticesSize!) * mono.sizeX, //eslint-disable-line @typescript-eslint/no-non-null-assertion
y: (j.y / mono.verticesSize!) * mono.sizeY, y: (j.y / mono.verticesSize!) * mono.sizeY, //eslint-disable-line @typescript-eslint/no-non-null-assertion
}))), options); }))), options);
} else { } else {
throw new Error('unrecognized shape'); throw new Error('unrecognized shape');
@ -227,7 +226,12 @@ export class DropAndFusionGame extends EventEmitter<{
this.gameOverReadyBodyIds = this.gameOverReadyBodyIds.filter(x => x !== bodyA.id && x !== bodyB.id); this.gameOverReadyBodyIds = this.gameOverReadyBodyIds.filter(x => x !== bodyA.id && x !== bodyB.id);
Matter.Composite.remove(this.engine.world, [bodyA, bodyB]); Matter.Composite.remove(this.engine.world, [bodyA, bodyB]);
const currentMono = this.monoDefinitions.find(y => y.id === bodyA.label)!; const currentMono = this.monoDefinitions.find(y => y.id === bodyA.label);
if (currentMono == null) {
throw new Error('Current Mono Not Found');
}
const nextMono = this.monoDefinitions.find(x => x.level === currentMono.level + 1) ?? null; const nextMono = this.monoDefinitions.find(x => x.level === currentMono.level + 1) ?? null;
if (nextMono) { if (nextMono) {
@ -362,14 +366,18 @@ export class DropAndFusionGame extends EventEmitter<{
} }
public getActiveMonos() { public getActiveMonos() {
return this.engine.world.bodies.map(x => this.monoDefinitions.find((mono) => mono.id === x.label)!).filter(x => x !== undefined); return this.engine.world.bodies
.map(x => this.monoDefinitions.find((mono) => mono.id === x.label))
.filter(x => x !== undefined);
} }
public drop(_x: number) { public drop(_x: number) {
if (this.isGameOver) return; if (this.isGameOver) return;
if (this.frame - this.latestDroppedAt < this.DROP_COOLTIME) return; if (this.frame - this.latestDroppedAt < this.DROP_COOLTIME) return;
const head = this.stock.shift()!; const head = this.stock.shift();
if (!head) return;
this.stock.push({ this.stock.push({
id: this.rng().toString(), id: this.rng().toString(),
mono: this.monoDefinitions.filter(x => x.dropCandidate)[Math.floor(this.rng() * this.monoDefinitions.filter(x => x.dropCandidate).length)], mono: this.monoDefinitions.filter(x => x.dropCandidate)[Math.floor(this.rng() * this.monoDefinitions.filter(x => x.dropCandidate).length)],
@ -411,13 +419,15 @@ export class DropAndFusionGame extends EventEmitter<{
}); });
if (this.holding) { if (this.holding) {
const head = this.stock.shift()!; const head = this.stock.shift();
if (!head) return;
this.stock.unshift(this.holding); this.stock.unshift(this.holding);
this.holding = head; this.holding = head;
this.emit('changeHolding', this.holding); this.emit('changeHolding', this.holding);
this.emit('changeStock', this.stock); this.emit('changeStock', this.stock);
} else { } else {
const head = this.stock.shift()!; const head = this.stock.shift();
if (!head) return;
this.holding = head; this.holding = head;
this.stock.push({ this.stock.push({
id: this.rng().toString(), id: this.rng().toString(),

View file

@ -1,32 +1,32 @@
import * as esbuild from "esbuild"; import fs from 'node:fs';
import { build } from "esbuild"; import { fileURLToPath } from 'node:url';
import { globSync } from "glob"; import { dirname } from 'node:path';
import { execa } from "execa"; import * as esbuild from 'esbuild';
import fs from "node:fs"; import { build } from 'esbuild';
import { fileURLToPath } from "node:url"; import { globSync } from 'glob';
import { dirname } from "node:path"; import { execa } from 'execa';
const _filename = fileURLToPath(import.meta.url); const _filename = fileURLToPath(import.meta.url);
const _dirname = dirname(_filename); const _dirname = dirname(_filename);
const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8')); const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8'));
const entryPoints = globSync("./src/**/**.{ts,tsx}"); const entryPoints = globSync('./src/**/**.{ts,tsx}');
/** @type {import('esbuild').BuildOptions} */ /** @type {import('esbuild').BuildOptions} */
const options = { const options = {
entryPoints, entryPoints,
minify: process.env.NODE_ENV === 'production', minify: process.env.NODE_ENV === 'production',
outdir: "./built", outdir: './built',
target: "es2022", target: 'es2022',
platform: "browser", platform: 'browser',
format: "esm", format: 'esm',
sourcemap: 'linked', sourcemap: 'linked',
}; };
// built配下をすべて削除する // built配下をすべて削除する
fs.rmSync('./built', { recursive: true, force: true }); fs.rmSync('./built', { recursive: true, force: true });
if (process.argv.map(arg => arg.toLowerCase()).includes("--watch")) { if (process.argv.map(arg => arg.toLowerCase()).includes('--watch')) {
await watchSrc(); await watchSrc();
} else { } else {
await buildSrc(); await buildSrc();
@ -36,7 +36,7 @@ async function buildSrc() {
console.log(`[${_package.name}] start building...`); console.log(`[${_package.name}] start building...`);
await build(options) await build(options)
.then(it => { .then(() => {
console.log(`[${_package.name}] build succeeded.`); console.log(`[${_package.name}] build succeeded.`);
}) })
.catch((err) => { .catch((err) => {
@ -65,7 +65,7 @@ function buildDts() {
{ {
stdout: process.stdout, stdout: process.stdout,
stderr: process.stderr, stderr: process.stderr,
} },
); );
} }
@ -86,7 +86,7 @@ async function watchSrc() {
}, },
}]; }];
console.log(`[${_package.name}] start watching...`) console.log(`[${_package.name}] start watching...`);
const context = await esbuild.context({ ...options, plugins }); const context = await esbuild.context({ ...options, plugins });
await context.watch(); await context.watch();

View file

@ -1,6 +1,7 @@
import tsParser from '@typescript-eslint/parser'; import tsParser from '@typescript-eslint/parser';
import sharedConfig from '../shared/eslint.config.js'; import sharedConfig from '../shared/eslint.config.js';
// eslint-disable-next-line import/no-default-export
export default [ export default [
...sharedConfig, ...sharedConfig,
{ {

View file

@ -53,9 +53,13 @@ export class Game {
//#region Options //#region Options
this.opts = opts; this.opts = opts;
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
if (this.opts.isLlotheo == null) this.opts.isLlotheo = false; if (this.opts.isLlotheo == null) this.opts.isLlotheo = false;
if (this.opts.canPutEverywhere == null) this.opts.canPutEverywhere = false; if (this.opts.canPutEverywhere == null) this.opts.canPutEverywhere = false;
if (this.opts.loopedBoard == null) this.opts.loopedBoard = false; if (this.opts.loopedBoard == null) this.opts.loopedBoard = false;
/* eslint-enable */
//#endregion //#endregion
//#region Parse map data //#region Parse map data
@ -123,12 +127,13 @@ export class Game {
// ターン計算 // ターン計算
this.turn = this.turn =
this.canPutSomewhere(!this.prevColor) ? !this.prevColor : this.canPutSomewhere(!this.prevColor) ? !this.prevColor :
this.canPutSomewhere(this.prevColor!) ? this.prevColor : this.canPutSomewhere(this.prevColor!) ? this.prevColor : //eslint-disable-line @typescript-eslint/no-non-null-assertion
null; null;
} }
public undo() { public undo() {
const undo = this.logs.pop()!; const undo = this.logs.pop();
if (undo == null) return;
this.prevColor = undo.color; this.prevColor = undo.color;
this.prevPos = undo.pos; this.prevPos = undo.pos;
this.board[undo.pos] = null; this.board[undo.pos] = null;
@ -183,7 +188,7 @@ export class Game {
const found: number[] = []; // 挟めるかもしれない相手の石を入れておく配列 const found: number[] = []; // 挟めるかもしれない相手の石を入れておく配列
let [x, y] = this.posToXy(initPos); let [x, y] = this.posToXy(initPos);
while (true) { while (true) { // eslint-disable-line @typescript-eslint/no-unnecessary-condition
[x, y] = nextPos(x, y); [x, y] = nextPos(x, y);
// 座標が指し示す位置がボード外に出たとき // 座標が指し示す位置がボード外に出たとき