Skip to content

Commit 2facd9a

Browse files
committed
plugin: configure biome style rules
1 parent bdf6e7f commit 2facd9a

File tree

29 files changed

+213
-76
lines changed

29 files changed

+213
-76
lines changed

biome.json

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,5 @@
11
{
2-
"$schema": "https://biomejs.dev/schemas/2.1.1/schema.json",
3-
"files": {
4-
"experimentalScannerIgnores": [
5-
"**/node_modules/**",
6-
"**/dist/**",
7-
"**/build/**",
8-
"**/.devenv/**",
9-
"**/.direnv/**"
10-
]
11-
},
2+
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
123
"formatter": {
134
"enabled": true,
145
"indentStyle": "space",
@@ -24,9 +15,75 @@
2415
},
2516
"a11y": {
2617
"noStaticElementInteractions": "off"
18+
},
19+
"style": {
20+
"noDefaultExport": "error",
21+
"noExportedImports": "error",
22+
"noInferrableTypes": "error",
23+
"noMagicNumbers": "error",
24+
"noNegationElse": "error",
25+
"noNestedTernary": "error",
26+
"noNonNullAssertion": "error",
27+
"noParameterAssign": "error",
28+
"noParameterProperties": "error",
29+
"noShoutyConstants": "error",
30+
"noUselessElse": "error",
31+
"noYodaExpression": "error",
32+
"useArrayLiterals": "error",
33+
"useAsConstAssertion": "error",
34+
"useBlockStatements": "error",
35+
"useCollapsedElseIf": "error",
36+
"useCollapsedIf": "error",
37+
"useConsistentArrayType": {
38+
"level": "error",
39+
"options": {
40+
"syntax": "shorthand"
41+
}
42+
},
43+
"useConsistentCurlyBraces": "error",
44+
"useConsistentObjectDefinitions": {
45+
"level": "error",
46+
"options": {
47+
"syntax": "shorthand"
48+
}
49+
},
50+
"useConst": "error",
51+
"useDefaultParameterLast": "error",
52+
"useDefaultSwitchClause": "error",
53+
"useEnumInitializers": "error",
54+
"useExplicitLengthCheck": "error",
55+
"useForOf": "error",
56+
"useFragmentSyntax": "error",
57+
"useImportType": "error",
58+
"useLiteralEnumMembers": "error",
59+
"useNumberNamespace": "error",
60+
"useNumericSeparators": "error",
61+
"useObjectSpread": "error",
62+
"useReactFunctionComponents": "error",
63+
"useReadonlyClassProperties": "error",
64+
"useSelfClosingElements": "error",
65+
"useShorthandFunctionType": "error",
66+
"useSingleVarDeclarator": "error",
67+
"useTemplate": "error",
68+
"useThrowNewError": "error",
69+
"useThrowOnlyError": "error"
2770
}
2871
}
2972
},
73+
"overrides": [
74+
{
75+
"includes": [
76+
"**/*.test.ts"
77+
],
78+
"linter": {
79+
"rules": {
80+
"style": {
81+
"noMagicNumbers": "off"
82+
}
83+
}
84+
}
85+
}
86+
],
3087
"assist": {
3188
"actions": {
3289
"source": {

plugin/src/api/domain/task.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,17 @@ export type Task = {
2929
order: number;
3030
};
3131

32-
export type Priority = 1 | 2 | 3 | 4;
32+
export const Priorities = {
33+
P4: 1,
34+
P3: 2,
35+
P2: 3,
36+
P1: 4,
37+
} as const;
38+
39+
export type Priority = (typeof Priorities)[keyof typeof Priorities];
3340

3441
export type CreateTaskParams = {
35-
priority: number;
42+
priority: Priority;
3643
projectId: ProjectId;
3744
description?: string;
3845
sectionId?: SectionId;

plugin/src/api/fetcher.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,25 @@ export interface WebFetcher {
44
fetch(params: RequestParams): Promise<WebResponse>;
55
}
66

7+
export type StatusCode = number;
8+
9+
export const StatusCode = {
10+
isError(code: StatusCode): boolean {
11+
return code >= StatusCodes.BadRequest;
12+
},
13+
isServerError(code: StatusCode): boolean {
14+
return code >= StatusCodes.InternalServerError;
15+
},
16+
} as const;
17+
18+
export const StatusCodes = {
19+
OK: 200,
20+
BadRequest: 400,
21+
Unauthorized: 401,
22+
Forbidden: 403,
23+
InternalServerError: 500,
24+
} as const;
25+
726
export type RequestParams = {
827
url: string;
928
method: string;
@@ -12,7 +31,7 @@ export type RequestParams = {
1231
};
1332

1433
export type WebResponse = {
15-
statusCode: number;
34+
statusCode: StatusCode;
1635
body: string;
1736
};
1837

plugin/src/api/index.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@ import type { Project } from "@/api/domain/project";
66
import type { Section } from "@/api/domain/section";
77
import type { CreateTaskParams, Task, TaskId } from "@/api/domain/task";
88
import type { UserInfo } from "@/api/domain/user";
9-
import type { RequestParams, WebFetcher, WebResponse } from "@/api/fetcher";
10-
import debug from "@/log";
9+
import { type RequestParams, StatusCode, type WebFetcher, type WebResponse } from "@/api/fetcher";
10+
import { debug } from "@/log";
1111

1212
type PaginatedResponse<T> = {
1313
results: T[];
1414
nextCursor: string | null;
1515
};
1616

1717
export class TodoistApiClient {
18-
private token: string;
19-
private fetcher: WebFetcher;
18+
private readonly token: string;
19+
private readonly fetcher: WebFetcher;
2020

2121
constructor(token: string, fetcher: WebFetcher) {
2222
this.token = token;
@@ -26,14 +26,14 @@ export class TodoistApiClient {
2626
public async getTasks(filter?: string): Promise<Task[]> {
2727
if (filter !== undefined) {
2828
return await this.doPaginated<Task>("/tasks/filter", { query: filter });
29-
} else {
30-
return await this.doPaginated<Task>("/tasks");
3129
}
30+
31+
return await this.doPaginated<Task>("/tasks");
3232
}
3333

3434
public async createTask(content: string, options?: CreateTaskParams): Promise<Task> {
3535
const body = snakify({
36-
content: content,
36+
content,
3737
...(options ?? {}),
3838
});
3939
const response = await this.do("/tasks", "POST", body);
@@ -87,7 +87,7 @@ export class TodoistApiClient {
8787
private async do(path: string, method: string, json?: object): Promise<WebResponse> {
8888
const params: RequestParams = {
8989
url: `https://api.todoist.com/api/v1${path}`,
90-
method: method,
90+
method,
9191
headers: {
9292
Authorization: `Bearer ${this.token}`,
9393
},
@@ -110,7 +110,7 @@ export class TodoistApiClient {
110110
context: response,
111111
});
112112

113-
if (response.statusCode >= 400) {
113+
if (StatusCode.isError(response.statusCode)) {
114114
throw new TodoistApiError(params, response);
115115
}
116116

@@ -119,7 +119,7 @@ export class TodoistApiClient {
119119
}
120120

121121
export class TodoistApiError extends Error {
122-
public statusCode: number;
122+
public statusCode: StatusCode;
123123

124124
constructor(request: RequestParams, response: WebResponse) {
125125
const message = `[${request.method}] ${request.url} returned '${response.statusCode}: ${response.body}`;

plugin/src/commands/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
import { t } from "@/i18n";
99
import type { Translations } from "@/i18n/translation";
1010
import type TodoistPlugin from "@/index";
11-
import debug from "@/log";
11+
import { debug } from "@/log";
1212

1313
export type MakeCommand = (
1414
plugin: TodoistPlugin,

plugin/src/data/deadline.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ const formatDeadline = (info: DeadlineInfo): string => {
8484
return i18n.lastWeekday(getFormatter("weekday").format(info.raw));
8585
case "nextWeek":
8686
return getFormatter("weekday").format(info.raw);
87+
default:
88+
break;
8789
}
8890

8991
if (!info.isCurrentYear) {

plugin/src/data/dueDate.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ const formatDate = (info: DateInfo): string => {
170170
return i18n.lastWeekday(getFormatter("weekday").format(info.raw));
171171
case "nextWeek":
172172
return getFormatter("weekday").format(info.raw);
173+
default:
174+
break;
173175
}
174176

175177
if (!info.isCurrentYear) {
@@ -194,6 +196,8 @@ const formatDueDateHeader = (due: DueDate): string => {
194196
case "tomorrow":
195197
parts.push(i18n.tomorrow);
196198
break;
199+
default:
200+
break;
197201
}
198202

199203
return parts.join(" ‧ ");

plugin/src/data/index.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { Project, ProjectId } from "@/api/domain/project";
44
import type { Section, SectionId } from "@/api/domain/section";
55
import type { Task as ApiTask, CreateTaskParams, TaskId } from "@/api/domain/task";
66
import type { UserInfo } from "@/api/domain/user";
7+
import { StatusCode, StatusCodes } from "@/api/fetcher";
78
import { Repository, type RepositoryReader } from "@/data/repository";
89
import { SubscriptionManager, type UnsubscribeCallback } from "@/data/subscriptions";
910
import type { Task } from "@/data/task";
@@ -146,10 +147,10 @@ export class TodoistAdapter {
146147
description: apiTask.description,
147148

148149
project: project ?? makeUnknownProject(apiTask.projectId),
149-
section: section,
150+
section,
150151
parentId: apiTask.parentId ?? undefined,
151152

152-
labels: labels,
153+
labels,
153154
priority: apiTask.priority,
154155

155156
due: apiTask.due ?? undefined,
@@ -253,13 +254,13 @@ class Subscription {
253254
kind: QueryErrorKind.Unknown,
254255
};
255256
if (error instanceof TodoistApiError) {
256-
if (error.statusCode === 400) {
257+
if (error.statusCode === StatusCodes.BadRequest) {
257258
result.kind = QueryErrorKind.BadRequest;
258-
} else if (error.statusCode === 401) {
259+
} else if (error.statusCode === StatusCodes.Unauthorized) {
259260
result.kind = QueryErrorKind.Unauthorized;
260-
} else if (error.statusCode === 403) {
261+
} else if (error.statusCode === StatusCodes.Forbidden) {
261262
result.kind = QueryErrorKind.Forbidden;
262-
} else if (error.statusCode > 500) {
263+
} else if (StatusCode.isServerError(error.statusCode)) {
263264
result.kind = QueryErrorKind.ServerError;
264265
}
265266
}

plugin/src/data/subscriptions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ export type UnsubscribeCallback = () => void;
33

44
export class SubscriptionManager<T> {
55
private readonly subscriptions: Map<SubscriptionId, T> = new Map();
6-
private generator: Generator<SubscriptionId> = subscriptionIdGenerator();
6+
private readonly generator: Generator<SubscriptionId> = subscriptionIdGenerator();
77

88
public subscribe(value: T): UnsubscribeCallback {
99
const id = this.generator.next().value;

plugin/src/data/transformations/grouping.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export function groupBy(tasks: Task[], groupBy: GroupVariant): GroupedTasks[] {
2424
case GroupVariant.Label:
2525
return groupByLabel(tasks);
2626
default:
27-
throw Error(`Cannot group by ${groupBy}`);
27+
throw new Error(`Cannot group by ${groupBy}`);
2828
}
2929
}
3030

0 commit comments

Comments
 (0)