Skip to content

Commit 5dc523a

Browse files
fix: even more issues
1 parent 1dd14b9 commit 5dc523a

13 files changed

+94
-56
lines changed

.eslintignore

-1
This file was deleted.

.eslintrc.js

+1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ module.exports = {
55
parserOptions: {
66
project: true,
77
},
8+
ignorePatterns: ["**/farcaster/generated/*.ts"],
89
};

packages/eslint-config/library.js

+2
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@ module.exports = {
3333
"@typescript-eslint/require-await": "warn",
3434
"@typescript-eslint/no-explicit-any": "warn",
3535
"@typescript-eslint/no-unnecessary-condition": "warn",
36+
"@typescript-eslint/consistent-type-imports": "error",
3637
"jest/expect-expect": "warn",
3738
"react/jsx-sort-props": "off",
3839
"unicorn/filename-case": "off",
3940
eqeqeq: "off",
41+
"no-await-in-loop": "off",
4042
},
4143
};

packages/frames.js/src/core/createFrames.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ export function createFrames<
3030
* This function takes handler function that does the logic with the help of context and returns one of possible results
3131
*/
3232
return function createFramesRequestHandler(handler, options = {}) {
33-
const perRouteMiddleware: FramesMiddleware<any, FramesContext<TState>>[] =
34-
Array.isArray(options.middleware) ? options.middleware : [];
33+
const perRouteMiddleware: FramesMiddleware<
34+
JsonValue | undefined,
35+
FramesContext<TState>
36+
>[] = Array.isArray(options.middleware) ? options.middleware : [];
3537

3638
const composedMiddleware = composeMiddleware<
3739
FramesContext<TState>,

packages/frames.js/src/getTokenFromUrl.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export function getTokenFromUrl(url: string): ParsedToken {
1515
}
1616

1717
return {
18-
namespace: namespace,
18+
namespace,
1919
chainId: parseInt(chainId),
2020
address,
2121
tokenId: tokenId || undefined,

packages/frames.js/src/hono/index.test.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ describe("hono adapter", () => {
88

99
it("correctly integrates with Hono", async () => {
1010
const frames = lib.createFrames();
11-
const handler = frames(async (ctx) => {
11+
const handler = frames((ctx) => {
1212
expect(ctx.request.url).toBe("http://localhost:3000/");
1313

1414
return {
1515
image: <span>Test</span>,
16-
buttons: [<lib.Button action="post">Click me</lib.Button>],
16+
buttons: [<lib.Button action="post" key="1">Click me</lib.Button>],
1717
};
1818
});
1919

@@ -39,7 +39,7 @@ describe("hono adapter", () => {
3939
},
4040
});
4141

42-
const handler = frames(async (ctx) => {
42+
const handler = frames((ctx) => {
4343
expect(ctx.state).toEqual({ test: false });
4444

4545
return {

packages/frames.js/src/hono/index.ts

+17-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
export { Button, type types } from "../core";
2-
import { createFrames as coreCreateFrames, types } from "../core";
31
import type { Handler } from "hono";
4-
import { CoreMiddleware } from "../middleware";
2+
import type { types } from "../core";
3+
import { createFrames as coreCreateFrames } from "../core";
4+
import type { CoreMiddleware } from "../middleware";
5+
6+
export { Button, type types } from "../core";
57

68
type CreateFramesForHono = types.CreateFramesFunctionDefinition<
79
CoreMiddleware,
@@ -12,6 +14,7 @@ type CreateFramesForHono = types.CreateFramesFunctionDefinition<
1214
* Creates Frames instance to use with you Hono server
1315
*
1416
* @example
17+
* ```tsx
1518
* import { createFrames, Button } from 'frames.js/hono';
1619
* import { Hono } from 'hono';
1720
*
@@ -30,17 +33,24 @@ type CreateFramesForHono = types.CreateFramesFunctionDefinition<
3033
* const app = new Hono();
3134
*
3235
* app.on(['GET', 'POST'], '/', honoHandler);
36+
* ```
3337
*/
34-
// @ts-expect-error
38+
// @ts-expect-error -- this code is correct just function doesn't satisfy the type
3539
export const createFrames: CreateFramesForHono = function createFramesForHono(
36-
options?: types.FramesOptions<any, any>
40+
options?: types.FramesOptions<types.JsonValue | undefined, undefined>
3741
) {
3842
const frames = coreCreateFrames(options);
3943

4044
return function honoFramesHandler<
41-
TPerRouteMiddleware extends types.FramesMiddleware<any, any>[],
45+
TPerRouteMiddleware extends types.FramesMiddleware<
46+
types.JsonValue | undefined,
47+
Record<string, unknown>
48+
>[],
4249
>(
43-
handler: types.FrameHandlerFunction<any, any>,
50+
handler: types.FrameHandlerFunction<
51+
types.JsonValue | undefined,
52+
Record<string, unknown>
53+
>,
4454
handlerOptions?: types.FramesRequestHandlerFunctionOptions<TPerRouteMiddleware>
4555
) {
4656
const framesHandler = frames(handler, handlerOptions);

packages/frames.js/src/hono/test.types.tsx

+27-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
import { Handler } from 'hono';
2-
import { createFrames, types } from '.';
1+
/* eslint-disable @typescript-eslint/require-await -- we are testing for promise compatibility */
2+
import type { Handler } from 'hono';
3+
import type { types } from '.';
4+
import { createFrames } from '.';
35

46
const framesWithoutState = createFrames();
57
framesWithoutState(async ctx => {
@@ -38,8 +40,29 @@ framesWithExplicitState(async ctx => {
3840
test: boolean;
3941
};
4042
ctx satisfies {
41-
message?: any;
42-
pressedButton?: any;
43+
message?: unknown;
44+
pressedButton?: unknown;
45+
request: Request;
46+
}
47+
48+
return {
49+
image: 'http://test.png'
50+
};
51+
}) satisfies Handler;
52+
53+
const framesWithExplicitStateNoPromise = createFrames<{
54+
test: boolean;
55+
}>({});
56+
framesWithExplicitStateNoPromise(ctx => {
57+
ctx.state satisfies {
58+
test: boolean;
59+
};
60+
ctx.initialState satisfies {
61+
test: boolean;
62+
};
63+
ctx satisfies {
64+
message?: unknown;
65+
pressedButton?: unknown;
4366
request: Request;
4467
}
4568

packages/frames.js/src/lib/stream-pump.ts

+29-30
Original file line numberDiff line numberDiff line change
@@ -27,28 +27,25 @@ export class StreamPump {
2727
new Stream.Readable().readableHighWaterMark;
2828
this.accumalatedSize = 0;
2929
this.stream = stream;
30-
this.enqueue = this.enqueue.bind(this);
31-
this.error = this.error.bind(this);
32-
this.close = this.close.bind(this);
3330
}
3431

35-
size(chunk: Uint8Array) {
36-
return chunk?.byteLength || 0;
32+
size(chunk: Uint8Array): number {
33+
return chunk.byteLength || 0;
3734
}
3835

39-
start(controller: ReadableStreamController<Uint8Array>) {
36+
start(controller: ReadableStreamController<Uint8Array>): void {
4037
this.controller = controller;
4138
this.stream.on("data", this.enqueue);
4239
this.stream.once("error", this.error);
4340
this.stream.once("end", this.close);
4441
this.stream.once("close", this.close);
4542
}
4643

47-
pull() {
44+
pull(): void {
4845
this.resume();
4946
}
5047

51-
cancel(reason?: Error) {
48+
cancel(reason?: Error): void {
5249
if (this.stream.destroy) {
5350
this.stream.destroy(reason);
5451
}
@@ -59,17 +56,17 @@ export class StreamPump {
5956
this.stream.off("close", this.close);
6057
}
6158

62-
enqueue(chunk: Uint8Array | string) {
59+
enqueue = (chunk: Uint8Array | string): void => {
6360
if (this.controller) {
6461
try {
65-
let bytes = chunk instanceof Uint8Array ? chunk : Buffer.from(chunk);
62+
const bytes = chunk instanceof Uint8Array ? chunk : Buffer.from(chunk);
6663

67-
let available = (this.controller.desiredSize || 0) - bytes.byteLength;
64+
const available = (this.controller.desiredSize || 0) - bytes.byteLength;
6865
this.controller.enqueue(bytes);
6966
if (available <= 0) {
7067
this.pause();
7168
}
72-
} catch (error: any) {
69+
} catch (error) {
7370
this.controller.error(
7471
new Error(
7572
"Could not create Buffer, chunk must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object"
@@ -78,60 +75,62 @@ export class StreamPump {
7875
this.cancel();
7976
}
8077
}
81-
}
78+
};
8279

83-
pause() {
80+
pause(): void {
8481
if (this.stream.pause) {
8582
this.stream.pause();
8683
}
8784
}
8885

89-
resume() {
86+
resume(): void {
9087
if (this.stream.readable && this.stream.resume) {
9188
this.stream.resume();
9289
}
9390
}
9491

95-
close() {
92+
close = (): void => {
9693
if (this.controller) {
9794
this.controller.close();
9895
delete this.controller;
9996
}
100-
}
97+
};
10198

102-
error(error: Error) {
99+
error = (error: Error): void => {
103100
if (this.controller) {
104101
this.controller.error(error);
105102
delete this.controller;
106103
}
107-
}
104+
};
108105
}
109106

110-
export const createReadableStreamFromReadable = (
107+
export function createReadableStreamFromReadable(
111108
source: Readable & { readableHighWaterMark?: number }
112-
) => {
113-
let pump = new StreamPump(source);
114-
let stream = new ReadableStream(pump, pump);
109+
): ReadableStream<Uint8Array> {
110+
const pump = new StreamPump(source);
111+
const stream = new ReadableStream(pump, pump);
115112
return stream;
116-
};
113+
}
117114

118-
export async function writeReadableStreamToWritable(
119-
stream: ReadableStream,
115+
export async function writeReadableStreamToWritable<R = any>(
116+
stream: ReadableStream<R>,
120117
writable: Writable
121-
) {
122-
let reader = stream.getReader();
123-
let flushable = writable as { flush?: Function };
118+
): Promise<void> {
119+
const reader = stream.getReader();
120+
const flushable = writable as { flush?: () => void };
124121

125122
try {
123+
// eslint-disable-next-line no-constant-condition, @typescript-eslint/no-unnecessary-condition -- this is expected to be exhaustive
126124
while (true) {
127-
let { done, value } = await reader.read();
125+
const { done, value } = await reader.read();
128126

129127
if (done) {
130128
writable.end();
131129
break;
132130
}
133131

134132
writable.write(value);
133+
135134
if (typeof flushable.flush === "function") {
136135
flushable.flush();
137136
}

packages/frames.js/src/middleware/farcasterHubContext.test.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Message } from "../farcaster";
22
import { redirect } from "../core/redirect";
33
import type { FramesContext } from "../core/types";
44
import { createFrames } from "../core";
5+
import type { UserDataReturnType } from "..";
56
import { farcasterHubContext } from "./farcasterHubContext";
67

78
describe("farcasterHubContext middleware", () => {
@@ -113,7 +114,7 @@ describe("farcasterHubContext middleware", () => {
113114
inputText: "hello",
114115
requesterFid: 123,
115116
state: JSON.stringify({ test: true }),
116-
requestedUserData: expect.anything(),
117+
requestedUserData: expect.anything() as UserDataReturnType,
117118
},
118119
})
119120
);

packages/frames.js/src/middleware/farcasterHubContext.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ async function decodeFrameActionPayloadFromRequest(
2929
): Promise<FrameActionPayload | undefined> {
3030
try {
3131
// use clone just in case someone wants to read body somewhere along the way
32-
const body = await request
32+
const body = (await request
3333
.clone()
3434
.json()
3535
.catch(() => {
3636
throw new RequestBodyNotJSONError();
37-
});
37+
})) as JSON;
3838

3939
if (!isValidFrameActionPayload(body)) {
4040
throw new InvalidFrameActionPayloadError();

packages/frames.js/src/middleware/openframes.test.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -208,17 +208,17 @@ describe("openframes middleware", () => {
208208
clientProtocol: "foo@vNext",
209209
handler: {
210210
isValidPayload: () => false,
211-
getFrameMessage: async () => {
212-
return { test1: true };
211+
getFrameMessage: () => {
212+
return Promise.resolve({ test1: true });
213213
},
214214
},
215215
});
216216
const mw2 = openframes({
217217
clientProtocol: "bar@vNext",
218218
handler: {
219219
isValidPayload: () => true,
220-
getFrameMessage: async () => {
221-
return { test2: true };
220+
getFrameMessage: () => {
221+
return Promise.resolve({ test2: true });
222222
},
223223
},
224224
});
@@ -227,7 +227,7 @@ describe("openframes middleware", () => {
227227
middleware: [mw1, mw2],
228228
});
229229

230-
const routeHandler = handler(async (ctx) => {
230+
const routeHandler = handler((ctx) => {
231231
return {
232232
image: `/?test1=${ctx.message?.test1}&test2=${ctx.message?.test2}`,
233233
};

packages/frames.js/src/validateFrameMessage.ts

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export async function validateFrameMessage(
4040
isValid: boolean;
4141
message: FrameActionMessage | undefined;
4242
}> {
43+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- just in case
4344
if (!body) {
4445
throw new Error(
4546
"Tried to call validateFrameMessage with no frame action payload. You may be calling it incorrectly on the homeframe"

0 commit comments

Comments
 (0)