diff --git a/.eslintrc.js b/.eslintrc.js index 10fff79..809afa3 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -24,6 +24,24 @@ module.exports = { 'no-void': ['error', {allowAsStatement: true}], 'no-console': ['error', {allow: ['info', 'error']}], '@typescript-eslint/unbound-method': 'off', - 'no-restricted-syntax': ['error', {allow: ['ForOfStatement']}] + 'no-restricted-syntax': [ + 'error', + { + selector: 'ForInStatement', + message: 'for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.', + }, + // { + // selector: 'ForOfStatement', + // message: 'iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations.', + // }, + { + selector: 'LabeledStatement', + message: 'Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.', + }, + { + selector: 'WithStatement', + message: '`with` is disallowed in strict mode because it makes code impossible to predict and optimize.', + }, + ], }, }; diff --git a/src/calendar.ts b/src/calendar.ts index f969fa7..e1faa72 100644 --- a/src/calendar.ts +++ b/src/calendar.ts @@ -1,7 +1,4 @@ -import { - ScheduleInterface, - SiteCalendarInterface, -} from './calendarInterface'; +import { ScheduleInterface, SiteCalendarInterface } from './calendarInterface'; import Retry from './lib/retry'; export default class Calendar { @@ -23,10 +20,11 @@ export default class Calendar { * @param {ScheduleInterface} schedule * @param calendarIds */ - static createEvent(schedule: ScheduleInterface, calendarIds: SiteCalendarInterface[]): void { - const siteCalendarId: - | SiteCalendarInterface - | undefined = calendarIds.find( + static createEvent( + schedule: ScheduleInterface, + calendarIds: SiteCalendarInterface[] + ): void { + const siteCalendarId: SiteCalendarInterface | undefined = calendarIds.find( (id) => id.type === schedule.type ); if (typeof siteCalendarId === 'undefined') { @@ -44,7 +42,7 @@ export default class Calendar { schedule.title, new Date(schedule.startTime), new Date(schedule.endTime), - {description: schedule.description} + { description: schedule.description } ); } else { CalendarApp.getCalendarById(calendarId).createAllDayEvent( diff --git a/src/oneMonthSchedule.ts b/src/oneMonthSchedule.ts index b5d885a..8407c36 100644 --- a/src/oneMonthSchedule.ts +++ b/src/oneMonthSchedule.ts @@ -1,9 +1,6 @@ import dayjs from 'dayjs'; import Calendar from './calendar'; -import { - ScheduleInterface, - SiteCalendarInterface, -} from './calendarInterface'; +import { ScheduleInterface, SiteCalendarInterface } from './calendarInterface'; import Retry from './lib/retry'; import 'regenerator-runtime'; @@ -15,7 +12,11 @@ export default class OneMonthSchedule { * @param siteCalendarIds * @returns {Promise} */ - static async setSchedule(date: dayjs.Dayjs, calendarUrl: string, siteCalendarIds: SiteCalendarInterface[]): Promise { + static async setSchedule( + date: dayjs.Dayjs, + calendarUrl: string, + siteCalendarIds: SiteCalendarInterface[] + ): Promise { const customUrl: string = calendarUrl + date.format('YYYYMMDD'); const scheduleJson = await OneMonthSchedule.getScheduleJson(customUrl); @@ -52,7 +53,10 @@ export default class OneMonthSchedule { * @param {dayjs.Dayjs} date * @param siteCalendarIds */ - private static delete1MonthCalendarEvents(date: dayjs.Dayjs, siteCalendarIds: SiteCalendarInterface[]) { + private static delete1MonthCalendarEvents( + date: dayjs.Dayjs, + siteCalendarIds: SiteCalendarInterface[] + ) { let deleteEventCallCount = 0; siteCalendarIds.forEach((siteCalendarId) => { if (process.env.ENV !== 'production') return; diff --git a/src/schedule.ts b/src/schedule.ts index a709753..ea3af63 100644 --- a/src/schedule.ts +++ b/src/schedule.ts @@ -1,13 +1,13 @@ import KeyakiSiteSchedule from './sites/keyakizaka/keyakiSiteSchedule'; -import {SiteScheduleInterface} from './sites/siteSchedule'; +import { SiteScheduleInterface } from './sites/siteSchedule'; export default class Schedule { static async setSchedule(): Promise { const siteScheduleList: SiteScheduleInterface[] = [ - new KeyakiSiteSchedule, + new KeyakiSiteSchedule(), // new KeyakiSiteSchedule ]; - for await(const siteSchedule of siteScheduleList) { + for await (const siteSchedule of siteScheduleList) { await siteSchedule.setSiteSchedule(); } } diff --git a/src/sites/keyakizaka/keyakiObjects.ts b/src/sites/keyakizaka/keyakiObjects.ts index 8fe7860..68c07e9 100644 --- a/src/sites/keyakizaka/keyakiObjects.ts +++ b/src/sites/keyakizaka/keyakiObjects.ts @@ -1,4 +1,4 @@ -import {SiteCalendarInterface} from '../../calendarInterface'; +import { SiteCalendarInterface } from '../../calendarInterface'; export const getKeyakiCalendarUrl = process.env.ENV === 'production' diff --git a/src/sites/keyakizaka/keyakiSiteSchedule.ts b/src/sites/keyakizaka/keyakiSiteSchedule.ts index ffff478..89bd676 100644 --- a/src/sites/keyakizaka/keyakiSiteSchedule.ts +++ b/src/sites/keyakizaka/keyakiSiteSchedule.ts @@ -1,6 +1,6 @@ import SiteSchedule from '../siteSchedule'; -import {getKeyakiCalendarUrl, keyakiCalendarIds} from './keyakiObjects'; -import {SiteCalendarInterface} from '../../calendarInterface'; +import { getKeyakiCalendarUrl, keyakiCalendarIds } from './keyakiObjects'; +import { SiteCalendarInterface } from '../../calendarInterface'; export default class KeyakiSiteSchedule extends SiteSchedule { // eslint-disable-next-line class-methods-use-this diff --git a/src/sites/siteSchedule.ts b/src/sites/siteSchedule.ts index 481fb65..1ecd0e5 100644 --- a/src/sites/siteSchedule.ts +++ b/src/sites/siteSchedule.ts @@ -1,7 +1,7 @@ import dayjs from 'dayjs'; import OneMonthSchedule from '../oneMonthSchedule'; import Trigger, { TERMINATION_MINUTES } from '../lib/trigger'; -import {SiteCalendarInterface} from '../calendarInterface'; +import { SiteCalendarInterface } from '../calendarInterface'; export interface SiteScheduleInterface { setSiteSchedule(): Promise; @@ -9,7 +9,7 @@ export interface SiteScheduleInterface { siteCalendarIds(): SiteCalendarInterface[]; } -export default abstract class SiteSchedule implements SiteScheduleInterface{ +export default abstract class SiteSchedule implements SiteScheduleInterface { async setSiteSchedule(): Promise { const beginningOfNexYearMonth = dayjs().startOf('month').add(1, 'year'); let targetBeginningOfMonth = SiteSchedule.getTargetBeginningOfMonth(); @@ -17,7 +17,11 @@ export default abstract class SiteSchedule implements SiteScheduleInterface{ while (targetBeginningOfMonth.isBefore(beginningOfNexYearMonth)) { // eslint-disable-next-line no-await-in-loop - await OneMonthSchedule.setSchedule(targetBeginningOfMonth, this.siteCalendarUrl(), this.siteCalendarIds()); + await OneMonthSchedule.setSchedule( + targetBeginningOfMonth, + this.siteCalendarUrl(), + this.siteCalendarIds() + ); targetBeginningOfMonth = targetBeginningOfMonth.add(1, 'month'); if (Trigger.hasExceededTerminationMinutes(startDate)) { Trigger.setTrigger(targetBeginningOfMonth); @@ -48,4 +52,3 @@ export default abstract class SiteSchedule implements SiteScheduleInterface{ abstract siteCalendarIds(): SiteCalendarInterface[]; } - diff --git a/tests/calendar.test.ts b/tests/calendar.test.ts index 65db5f0..5169d95 100644 --- a/tests/calendar.test.ts +++ b/tests/calendar.test.ts @@ -1,6 +1,6 @@ import Calendar from '../src/calendar'; import { ScheduleInterface } from '../src/calendarInterface'; -import {keyakiCalendarIds} from '../src/sites/keyakizaka/keyakiObjects'; +import { keyakiCalendarIds } from '../src/sites/keyakizaka/keyakiObjects'; /** * diff --git a/tests/oneMonthSchedule.test.ts b/tests/oneMonthSchedule.test.ts index d9b8772..0794339 100644 --- a/tests/oneMonthSchedule.test.ts +++ b/tests/oneMonthSchedule.test.ts @@ -2,7 +2,10 @@ import dayjs from 'dayjs'; import fetchMock from 'jest-fetch-mock'; import OneMonthSchedule from '../src/oneMonthSchedule'; import Calendar from '../src/calendar'; -import {getKeyakiCalendarUrl, keyakiCalendarIds} from '../src/sites/keyakizaka/keyakiObjects'; +import { + getKeyakiCalendarUrl, + keyakiCalendarIds, +} from '../src/sites/keyakizaka/keyakiObjects'; function getScheduleJson() { return '[{"title":"欅坂46 こちら有楽町星空放送局","start":"2019-12-01","className":"media","description":"欅坂46 こちら有楽町星空放送局"},{"title":"テレビ東京「欅って、書けない?」","start":"2019-12-01","className":"media","description":"テレビ東京「欅って、書けない?」"}]'; @@ -35,7 +38,13 @@ describe('setSchedule', () => { })) as jest.Mock; const date = dayjs('2019-12-01'); - await expect(OneMonthSchedule.setSchedule(date, getKeyakiCalendarUrl, keyakiCalendarIds)).resolves.not.toThrow(); + await expect( + OneMonthSchedule.setSchedule( + date, + getKeyakiCalendarUrl, + keyakiCalendarIds + ) + ).resolves.not.toThrow(); expect(Calendar.deleteEvent).toBeCalledTimes( keyakiCalendarIds.length * date.endOf('month').date() ); @@ -61,7 +70,13 @@ describe('setSchedule', () => { }); const date = dayjs('2019-12-01'); - await expect(OneMonthSchedule.setSchedule(date, getKeyakiCalendarUrl, keyakiCalendarIds)).rejects.toThrow(); + await expect( + OneMonthSchedule.setSchedule( + date, + getKeyakiCalendarUrl, + keyakiCalendarIds + ) + ).rejects.toThrow(); expect(Calendar.createEvent).not.toBeCalled(); }); it('カレンダーの作成に失敗した場合に例外が起きて後続の処理が止まること', async () => { @@ -83,7 +98,13 @@ describe('setSchedule', () => { }); const date = dayjs('2019-12-01'); - await expect(OneMonthSchedule.setSchedule(date, getKeyakiCalendarUrl, keyakiCalendarIds)).rejects.toThrow(); + await expect( + OneMonthSchedule.setSchedule( + date, + getKeyakiCalendarUrl, + keyakiCalendarIds + ) + ).rejects.toThrow(); }); it('production環境では無かった場合にUrlFetchApp.fetchが呼ばれないこと', async () => { process.env.ENV = 'local'; @@ -91,7 +112,11 @@ describe('setSchedule', () => { fetchMock.mockOnce(getScheduleJson()); const date = dayjs('2019-12-01'); - await OneMonthSchedule.setSchedule(date, getKeyakiCalendarUrl, keyakiCalendarIds); + await OneMonthSchedule.setSchedule( + date, + getKeyakiCalendarUrl, + keyakiCalendarIds + ); expect(UrlFetchApp.fetch).not.toBeCalled(); }); });