Skip to content

Commit 30ff060

Browse files
committed
style: add eslint
1 parent 4d78609 commit 30ff060

File tree

19 files changed

+339
-92
lines changed

19 files changed

+339
-92
lines changed

.github/workflows/deploy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
- name: "Test"
2323
run: |
2424
yarn prettier -c .
25-
yarn tsc --noEmit
25+
yarn eslint .
2626
yarn test
2727
2828
- name: "Deploy"

.github/workflows/pr.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
- name: "Test"
3535
run: |
3636
yarn prettier -c .
37-
yarn tsc --noEmit
37+
yarn eslint .
3838
yarn test
3939
4040
- name: "Run Coverage"

eslint.config.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// @ts-check
2+
3+
import eslint from "@eslint/js"
4+
import tseslint from "typescript-eslint"
5+
import { globalIgnores } from "eslint/config"
6+
7+
export default tseslint.config(
8+
eslint.configs.recommended,
9+
tseslint.configs.recommendedTypeChecked,
10+
{
11+
languageOptions: {
12+
parserOptions: {
13+
projectService: true,
14+
tsconfigRootDir: import.meta.dirname,
15+
},
16+
},
17+
},
18+
globalIgnores([
19+
"dist/**",
20+
".wrangler/**",
21+
"coverage/**",
22+
"worker-configuration.d.ts",
23+
]),
24+
{
25+
rules: {
26+
"no-unused-vars": "off",
27+
"@typescript-eslint/no-unused-vars": [
28+
"error",
29+
{
30+
argsIgnorePattern: "^_",
31+
varsIgnorePattern: "^_",
32+
},
33+
],
34+
},
35+
},
36+
{
37+
files: ["*.config.js"], // TODO: make them work
38+
extends: [tseslint.configs.disableTypeChecked],
39+
},
40+
)

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"delete-paste": "wrangler kv:key delete --binding PB",
1313
"test": "vitest",
1414
"fmt": "prettier --write .",
15+
"lint": "eslint .",
1516
"coverage": "vitest run --coverage"
1617
},
1718
"author": "SharzyL <[email protected]>",
@@ -24,6 +25,7 @@
2425
"eslint": "^9.25.0",
2526
"prettier": "^3.5.3",
2627
"typescript": "^5.8.3",
28+
"typescript-eslint": "^8.30.1",
2729
"vitest": "3.1.1",
2830
"wrangler": "^4.12.0"
2931
},

src/common.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
import { FormDataDisposition } from "./parseFormdata.js"
2-
31
export const params = {
42
CHAR_GEN: "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678",
5-
NAME_REGEX: /^[a-zA-Z0-9+_\-\[\]*$@,;]{3,}$/,
3+
NAME_REGEX: /^[a-zA-Z0-9+_\-[\]*$@,;]{3,}$/,
64
PASTE_NAME_LEN: 4,
75
PRIVATE_PASTE_NAME_LEN: 24,
86
DEFAULT_PASSWD_LEN: 24,
@@ -29,8 +27,8 @@ export function atob_utf8(value: string): string {
2927

3028
export class WorkerError extends Error {
3129
public statusCode: number
32-
constructor(statusCode: number, ...params: any[]) {
33-
super(...params)
30+
constructor(statusCode: number, msg: string) {
31+
super(msg)
3432
this.statusCode = statusCode
3533
}
3634
}
@@ -79,20 +77,20 @@ export function parsePath(pathname: string): ParsedPath {
7977
}
8078

8179
// extract and remove filename
82-
let startOfFilename = pathname.lastIndexOf("/")
80+
const startOfFilename = pathname.lastIndexOf("/")
8381
if (startOfFilename >= 0) {
8482
filename = pathname.slice(startOfFilename + 1)
8583
pathname = pathname.slice(0, startOfFilename)
8684
}
8785

8886
// if having filename, parse ext from filename, else from remaining pathname
8987
if (filename) {
90-
let startOfExt = filename.indexOf(".")
88+
const startOfExt = filename.indexOf(".")
9189
if (startOfExt >= 0) {
9290
ext = filename.slice(startOfExt)
9391
}
9492
} else {
95-
let startOfExt = pathname.indexOf(".")
93+
const startOfExt = pathname.indexOf(".")
9694
if (startOfExt >= 0) {
9795
ext = pathname.slice(startOfExt)
9896
pathname = pathname.slice(0, startOfExt)

src/handlers/handleCors.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ const corsHeaders = {
55
}
66

77
export function handleOptions(request: Request) {
8-
let headers = request.headers
8+
const headers = request.headers
99
if (
1010
headers.get("Origin") !== null &&
1111
headers.get("Access-Control-Request-Method") !== null
1212
) {
13-
let respHeaders: { [name: string]: string } = corsHeaders
13+
const respHeaders: { [name: string]: string } = corsHeaders
1414
if ("Access-Control-Request-Methods" in respHeaders) {
1515
respHeaders["Access-Control-Allow-Headers"] = request.headers.get(
1616
"Access-Control-Request-Headers",

src/handlers/handleWrite.ts

Lines changed: 31 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ import {
1616
updatePaste,
1717
} from "../storage/storage.js"
1818

19-
type PasteResponse = {
19+
export type PasteResponse = {
2020
url: string
2121
suggestedUrl?: string
2222
manageUrl: string
2323
expirationSeconds: number
24+
expireAt: string
2425
}
2526

2627
function suggestUrl(
@@ -63,7 +64,7 @@ export async function handlePostOrPut(
6364
const uint8Array = new Uint8Array(await request.arrayBuffer())
6465
try {
6566
form = parseFormdata(uint8Array, getBoundary(contentType))
66-
} catch (e) {
67+
} catch {
6768
throw new WorkerError(400, "error occurs when parsing formdata")
6869
}
6970
} else {
@@ -92,7 +93,7 @@ export async function handlePostOrPut(
9293

9394
// parse expiration
9495
let expirationSeconds = parseExpiration(expire)
95-
let maxExpiration = parseExpiration(env.MAX_EXPIRATION)
96+
const maxExpiration = parseExpiration(env.MAX_EXPIRATION)
9697
if (expirationSeconds > maxExpiration) {
9798
expirationSeconds = maxExpiration
9899
}
@@ -105,22 +106,10 @@ export async function handlePostOrPut(
105106
)
106107
}
107108

108-
function makeResponse(created: PasteResponse, now: Date): Response {
109-
return new Response(
110-
JSON.stringify(
111-
{
112-
...created,
113-
expiredAt: new Date(
114-
now.getTime() + 1000 * created.expirationSeconds,
115-
).toISOString(),
116-
},
117-
null,
118-
2,
119-
),
120-
{
121-
headers: { "content-type": "application/json;charset=UTF-8" },
122-
},
123-
)
109+
function makeResponse(created: PasteResponse): Response {
110+
return new Response(JSON.stringify(created, null, 2), {
111+
headers: { "content-type": "application/json;charset=UTF-8" },
112+
})
124113
}
125114

126115
function accessUrl(short: string): string {
@@ -131,7 +120,7 @@ export async function handlePostOrPut(
131120
return env.BASE_URL + "/" + short + params.SEP + passwd
132121
}
133122

134-
let now = new Date()
123+
const now = new Date()
135124
if (isPut) {
136125
const { nameFromPath, passwd } = parsePath(url.pathname)
137126
const originalMetadata = await getPasteMetadata(env, nameFromPath)
@@ -146,27 +135,27 @@ export async function handlePostOrPut(
146135
`incorrect password for paste '${nameFromPath}`,
147136
)
148137
} else {
149-
let pasteName =
138+
const pasteName =
150139
nameFromPath ||
151140
genRandStr(
152141
isPrivate ? params.PRIVATE_PASTE_NAME_LEN : params.PASTE_NAME_LEN,
153142
)
154-
let newPasswd = passwdFromForm || passwd
143+
const newPasswd = passwdFromForm || passwd
155144
await updatePaste(env, pasteName, content, originalMetadata, {
156145
expirationSeconds,
157146
now,
158147
passwd: newPasswd,
159148
filename,
160149
})
161-
return makeResponse(
162-
{
163-
url: accessUrl(pasteName),
164-
suggestedUrl: suggestUrl(content, pasteName, env.BASE_URL, filename),
165-
manageUrl: manageUrl(pasteName, newPasswd),
166-
expirationSeconds,
167-
},
168-
now,
169-
)
150+
return makeResponse({
151+
url: accessUrl(pasteName),
152+
suggestedUrl: suggestUrl(content, pasteName, env.BASE_URL, filename),
153+
manageUrl: manageUrl(pasteName, newPasswd),
154+
expirationSeconds,
155+
expireAt: new Date(
156+
now.getTime() + 1000 * expirationSeconds,
157+
).toISOString(),
158+
})
170159
}
171160
} else {
172161
let pasteName: string | undefined
@@ -181,25 +170,25 @@ export async function handlePostOrPut(
181170
)
182171
}
183172

184-
let passwd = passwdFromForm || genRandStr(params.DEFAULT_PASSWD_LEN)
173+
const passwd = passwdFromForm || genRandStr(params.DEFAULT_PASSWD_LEN)
185174
if (passwd.length === 0) {
186175
throw new WorkerError(400, "Empty passwd is not allowed")
187176
}
188-
await createPaste(env, pasteName!, content, {
177+
await createPaste(env, pasteName, content, {
189178
expirationSeconds,
190179
now,
191180
passwd,
192181
filename,
193182
})
194183

195-
return makeResponse(
196-
{
197-
url: accessUrl(pasteName),
198-
suggestedUrl: suggestUrl(content, pasteName, env.BASE_URL, filename),
199-
manageUrl: manageUrl(pasteName, passwd),
200-
expirationSeconds,
201-
},
202-
now,
203-
)
184+
return makeResponse({
185+
url: accessUrl(pasteName),
186+
suggestedUrl: suggestUrl(content, pasteName, env.BASE_URL, filename),
187+
manageUrl: manageUrl(pasteName, passwd),
188+
expirationSeconds,
189+
expireAt: new Date(
190+
now.getTime() + 1000 * expirationSeconds,
191+
).toISOString(),
192+
})
204193
}
205194
}

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ async function handleRequest(
3939
}),
4040
)
4141
} else {
42-
let err = e as Error
42+
const err = e as Error
4343
console.log(err.stack)
4444
return corsWrapResponse(
4545
new Response(`Error 500: ${err.message}\n`, { status: 500 }),

src/pages/markdown.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { unified } from "unified"
2+
import { Root } from "mdast"
23
import remarkParse from "remark-parse"
34
import remarkGfm from "remark-gfm"
45
import remarkRehype from "remark-rehype"
@@ -15,8 +16,8 @@ type DocMetadata = {
1516
description: string
1617
}
1718

18-
function getMetadata(options: { result: DocMetadata }): (tree: any) => void {
19-
return (tree) => {
19+
function getMetadata(options: { result: DocMetadata }): (_: Root) => void {
20+
return (tree: Root) => {
2021
if (tree.children.length === 0) return
2122

2223
const firstChild = tree.children[0]

src/parseFormdata.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export function parseFormdata(
103103
break
104104
}
105105
}
106-
let key = decode(line.slice(0, curIdx + 1))
106+
const key = decode(line.slice(0, curIdx + 1))
107107

108108
curIdx++ // now curIdx points to the next char after ':'
109109
while (curIdx < line.length) {
@@ -114,7 +114,7 @@ export function parseFormdata(
114114
}
115115
}
116116

117-
let value = decode(line.slice(curIdx))
117+
const value = decode(line.slice(curIdx))
118118
return [key, value]
119119
}
120120

@@ -144,8 +144,6 @@ export function parseFormdata(
144144
return LineType.NORMAL
145145
}
146146

147-
let decoder = new TextDecoder()
148-
149147
enum DecoderState {
150148
WANT_HEADER,
151149
WANT_BODY,
@@ -154,12 +152,12 @@ export function parseFormdata(
154152
// 0: expecting a header
155153
// 1: expecting body or boundary
156154
let state = DecoderState.WANT_HEADER
157-
let parts: Map<string, FormDataPart> = new Map()
155+
const parts: Map<string, FormDataPart> = new Map()
158156
let lineStart = readLine(0) + 2
159157

160158
let bodyStartIdx = 0
161159
let curDisposition: FormDataDisposition | undefined = undefined
162-
let curHeaders: Map<string, string> = new Map()
160+
const curHeaders: Map<string, string> = new Map()
163161

164162
while (true) {
165163
const lineEnd = readLine(lineStart)
@@ -181,7 +179,7 @@ export function parseFormdata(
181179
const lineType = getLineType(line)
182180
if (lineType !== LineType.NORMAL) {
183181
// current line is boundary or EOF
184-
let content = uint8Array.subarray(bodyStartIdx, lineStart - 2)
182+
const content = uint8Array.subarray(bodyStartIdx, lineStart - 2)
185183
parts.set(curDisposition!.name, {
186184
disposition: curDisposition!,
187185
headers: curHeaders,

0 commit comments

Comments
 (0)