Skip to content

Commit e5f8f02

Browse files
authored
Merge pull request #266 from framesjs/build/eslint
build: change eslint configuration
2 parents f43396c + 84283a8 commit e5f8f02

File tree

93 files changed

+1371
-936
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+1371
-936
lines changed

.changeset/calm-carpets-divide.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@frames.js/render": minor
3+
---
4+
5+
feat: rename types

.changeset/chilly-parrots-sneeze.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"frames.js": patch
3+
"@frames.js/debugger": patch
4+
---
5+
6+
fix: minor bugs and code cleanup

.eslintrc.js

+1-4
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,8 @@
22
/** @type {import("eslint").Linter.Config} */
33
module.exports = {
44
extends: ["@framesjs/eslint-config/library.js"],
5-
parser: "@typescript-eslint/parser",
65
parserOptions: {
76
project: true,
87
},
9-
env: {
10-
jest: true,
11-
},
8+
ignorePatterns: ["**/farcaster/generated/*.ts"],
129
};

.github/workflows/github-actions.yml

+3
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ jobs:
5050
- name: Install dependencies
5151
run: yarn --frozen-lockfile
5252

53+
- name: Build
54+
run: yarn build:ci
55+
5356
- name: Lint
5457
run: yarn lint
5558

packages/debugger/app/components/frame-debugger.tsx

+26-15
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { getFrameHtmlHead, getFrameFlattened } from "frames.js";
22
import { Dispatch, SetStateAction, useEffect, useMemo, useState } from "react";
33
import React from "react";
4-
import { FrameState, FrameRequest, FrameStackSuccess } from "frames.js/render";
4+
import { FrameState, FrameStackSuccess } from "@frames.js/render";
55
import { Table, TableBody, TableCell, TableRow } from "@/components/table";
66
import {
77
AlertTriangle,
@@ -10,7 +10,6 @@ import {
1010
HomeIcon,
1111
ListIcon,
1212
LoaderIcon,
13-
MessageCircle,
1413
MessageCircleHeart,
1514
RefreshCwIcon,
1615
XCircle,
@@ -190,20 +189,22 @@ export function FrameDebugger({
190189

191190
const [openAccordions, setOpenAccordions] = useState<string[]>([]);
192191

192+
const [latestFrame] = frameState.framesStack;
193+
193194
useEffect(() => {
194195
if (!frameState.isLoading) {
195196
// make sure the first frame is open
196197
if (
197198
!openAccordions.includes(
198-
String(frameState.framesStack[0]?.timestamp.getTime())
199+
String(latestFrame?.timestamp.getTime())
199200
)
200201
)
201202
setOpenAccordions((v) => [
202203
...v,
203-
String(frameState.framesStack[0]?.timestamp.getTime()),
204+
String(latestFrame?.timestamp.getTime()),
204205
]);
205206
}
206-
}, [frameState.isLoading]);
207+
}, [frameState.isLoading, latestFrame?.timestamp, openAccordions]);
207208

208209
return (
209210
<div className="flex flex-row items-start p-4 gap-4 bg-slate-50 max-w-full w-full h-full">
@@ -219,7 +220,6 @@ export function FrameDebugger({
219220
frameState.fetchFrame({
220221
url: frameState?.homeframeUrl,
221222
method: "GET",
222-
request: {},
223223
});
224224
}}
225225
>
@@ -235,7 +235,6 @@ export function FrameDebugger({
235235
frameState.fetchFrame({
236236
url: frameState?.homeframeUrl,
237237
method: "GET",
238-
request: {},
239238
});
240239
}
241240
}}
@@ -246,12 +245,21 @@ export function FrameDebugger({
246245
className="flex flex-row gap-3 items-center shadow-sm border"
247246
variant={"outline"}
248247
onClick={() => {
249-
if (frameState?.framesStack[0]?.request) {
250-
frameState.fetchFrame({
251-
url: frameState?.framesStack[0].url,
252-
method: frameState?.framesStack[0].method,
253-
request: frameState.framesStack[0].request,
254-
} as FrameRequest);
248+
const [latestFrame] = frameState.framesStack;
249+
250+
if (latestFrame) {
251+
frameState.fetchFrame(
252+
latestFrame.method === "GET"
253+
? {
254+
method: "GET",
255+
url: latestFrame.url,
256+
}
257+
: {
258+
method: "POST",
259+
request: latestFrame.request,
260+
url: latestFrame.url,
261+
}
262+
);
255263
}
256264
}}
257265
>
@@ -269,11 +277,14 @@ export function FrameDebugger({
269277
className={`px-4 py-3 flex flex-col gap-2 ${i !== 0 ? "border-t" : "bg-slate-50"} hover:bg-slate-50 w-full`}
270278
key={frameStackItem.timestamp.getTime()}
271279
onClick={() => {
272-
frameState.fetchFrame({
280+
frameState.fetchFrame(frameStackItem.method === 'GET' ? {
281+
method: 'GET',
282+
url: frameStackItem.url,
283+
} : {
273284
url: frameStackItem.url,
274285
method: frameStackItem.method,
275286
request: frameStackItem.request,
276-
} as FrameRequest);
287+
});
277288
}}
278289
>
279290
<span className="flex text-left flex-row w-full">

packages/debugger/app/page.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export default function App({
6060
}, []);
6161

6262
useEffect(() => {
63-
if (url !== urlInput && url) {
63+
if (url) {
6464
setUrlInput(url);
6565
}
6666
}, [url]);

packages/eslint-config/library.js

+19-9
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,12 @@ const project = resolve(process.cwd(), "tsconfig.json");
44

55
/** @type {import("eslint").Linter.Config} */
66
module.exports = {
7-
extends: ["eslint:recommended", "prettier", "eslint-config-turbo"],
8-
plugins: ["only-warn"],
9-
globals: {
10-
React: true,
11-
JSX: true,
12-
},
13-
env: {
14-
node: true,
15-
},
7+
extends: [
8+
require.resolve("@vercel/style-guide/eslint/node"),
9+
require.resolve("@vercel/style-guide/eslint/jest-react"),
10+
require.resolve("@vercel/style-guide/eslint/react"),
11+
require.resolve("@vercel/style-guide/eslint/typescript"),
12+
],
1613
settings: {
1714
"import/resolver": {
1815
typescript: {
@@ -31,4 +28,17 @@ module.exports = {
3128
files: ["*.js?(x)", "*.ts?(x)"],
3229
},
3330
],
31+
rules: {
32+
"@typescript-eslint/consistent-type-definitions": "off",
33+
"@typescript-eslint/require-await": "warn",
34+
"@typescript-eslint/no-explicit-any": "warn",
35+
"@typescript-eslint/no-unnecessary-condition": "warn",
36+
"@typescript-eslint/consistent-type-imports": "error",
37+
"jest/expect-expect": "warn",
38+
"react/jsx-sort-props": "off",
39+
"unicorn/filename-case": "off",
40+
eqeqeq: "off",
41+
"no-await-in-loop": "off",
42+
"no-implicit-coercion": "off",
43+
},
3444
};

packages/frames.js/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@
250250
"@types/express": "^4.17.21",
251251
"@xmtp/frames-client": "^0.4.3",
252252
"@xmtp/frames-validator": "^0.5.2",
253+
"@xmtp/proto": "3.45.0",
253254
"@xmtp/xmtp-js": "^11.5.0",
254255
"express": "^4.19.1",
255256
"hono": "^4.1.3",
@@ -262,6 +263,7 @@
262263
"@cloudflare/workers-types": "^4.20240320.1",
263264
"@types/express": "^4.17.21",
264265
"@xmtp/frames-validator": "^0.5.2",
266+
"@xmtp/proto": "3.45.0",
265267
"next": "^14.1.0",
266268
"react": "^18.2.0",
267269
"react-dom": "^18.2.0"

packages/frames.js/src/cloudflare-workers/index.test.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ describe("cloudflare workers adapter", () => {
77

88
it("correctly integrates with Cloudflare Workers", async () => {
99
const frames = lib.createFrames();
10-
const handler = frames(async (ctx) => {
10+
const handler = frames((ctx) => {
1111
expect(ctx.request.url).toBe("http://localhost:3000/");
1212

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

@@ -35,7 +35,7 @@ describe("cloudflare workers adapter", () => {
3535
},
3636
});
3737

38-
const handler = frames(async (ctx) => {
38+
const handler = frames((ctx) => {
3939
expect(ctx.state).toEqual({ test: false });
4040

4141
return {

packages/frames.js/src/cloudflare-workers/index.ts

+15-10
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
1-
export { Button, type types } from "../core";
2-
import { createFrames as coreCreateFrames, types } from "../core";
3-
import type { CoreMiddleware } from "../middleware";
41
import { Buffer } from "node:buffer";
5-
import {
6-
type CloudflareWorkersMiddleware,
7-
cloudflareWorkersMiddleware,
8-
} from "./middleware";
92
import type { ExportedHandlerFetchHandler } from "@cloudflare/workers-types";
3+
import type { types } from "../core";
4+
import { createFrames as coreCreateFrames } from "../core";
105
import type {
116
FramesMiddleware,
127
FramesRequestHandlerFunction,
138
JsonValue,
149
} from "../core/types";
10+
import type { CoreMiddleware } from "../middleware";
11+
import {
12+
type CloudflareWorkersMiddleware,
13+
cloudflareWorkersMiddleware,
14+
} from "./middleware";
15+
16+
export { Button, type types } from "../core";
1517

1618
export { cloudflareWorkersMiddleware } from "./middleware";
1719

1820
// make Buffer available on globalThis so it is compatible with cloudflare workers
19-
// eslint-disable-next-line no-undef
2021
globalThis.Buffer = Buffer;
2122

2223
type DefaultMiddleware<TEnv> = [
@@ -28,6 +29,7 @@ type DefaultMiddleware<TEnv> = [
2829
* Creates Frames instance to use with you Hono server
2930
*
3031
* @example
32+
* ```ts
3133
* import { createFrames, Button } from 'frames.js/cloudflare-workers';
3234
*
3335
* const frames = createFrames();
@@ -41,8 +43,10 @@ type DefaultMiddleware<TEnv> = [
4143
* ],
4244
* };
4345
* });
46+
* ```
4447
*
4548
* @example
49+
* ```ts
4650
* // With custom type for Env and state
4751
* import { createFrames, Button, type types } from 'frames.js/cloudflare-workers';
4852
*
@@ -67,6 +71,7 @@ type DefaultMiddleware<TEnv> = [
6771
* export default {
6872
* fetch,
6973
* } satisfies ExportedHandler;
74+
* ```
7075
*/
7176
export function createFrames<
7277
TState extends JsonValue | undefined = JsonValue | undefined,
@@ -80,7 +85,7 @@ export function createFrames<
8085
TState,
8186
DefaultMiddleware<TEnv>,
8287
TFramesMiddleware,
83-
ExportedHandlerFetchHandler<TEnv, unknown>
88+
ExportedHandlerFetchHandler<TEnv>
8489
> {
8590
return function cloudflareWorkersFramesHandler<
8691
TPerRouteMiddleware extends
@@ -107,7 +112,7 @@ export function createFrames<
107112
return framesHandler(
108113
// @ts-expect-error - req is almost compatible, there are some differences in the types but it mostly fits all the needs
109114
req
110-
) as unknown as ReturnType<ExportedHandlerFetchHandler<unknown>>;
115+
) as unknown as ReturnType<ExportedHandlerFetchHandler>;
111116
};
112117
};
113118
}

packages/frames.js/src/cloudflare-workers/middleware.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type {
33
IncomingRequestCfProperties,
44
Request,
55
} from "@cloudflare/workers-types";
6-
import type { FramesMiddleware } from "../core/types";
6+
import type { FramesMiddleware, JsonValue } from "../core/types";
77

88
type CloudflareWorkersMiddlewareContext<TEnv> = {
99
/**
@@ -34,7 +34,7 @@ type CloudflareWorkersMiddlewareOptions<TEnv> = {
3434
};
3535

3636
export type CloudflareWorkersMiddleware<TEnv> = FramesMiddleware<
37-
any,
37+
JsonValue | undefined,
3838
CloudflareWorkersMiddlewareContext<TEnv>
3939
>;
4040

packages/frames.js/src/cloudflare-workers/test.types.tsx

+17-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
import { ExecutionContext, Request as CfRequest, ExportedHandlerFetchHandler } from '@cloudflare/workers-types';
2-
import { createFrames, types } from '.';
1+
/* eslint-disable @typescript-eslint/require-await -- we want to test that handler supports async*/
2+
import type { ExecutionContext, Request as CfRequest, ExportedHandlerFetchHandler } from '@cloudflare/workers-types';
3+
import type { types } from '.';
4+
import { createFrames } from '.';
35

46
const framesWithoutState = createFrames();
57
framesWithoutState(async (ctx) => {
@@ -26,7 +28,7 @@ framesWithInferredState(async (ctx) => {
2628
const framesWithExplicitState = createFrames<{ test: boolean }>({});
2729
framesWithExplicitState(async (ctx) => {
2830
ctx.state satisfies { test: boolean };
29-
ctx satisfies { initialState?: {test: boolean}; message?: any, pressedButton?: any };
31+
ctx satisfies { initialState?: {test: boolean}; message?: unknown, pressedButton?: unknown };
3032
ctx satisfies { cf: { env: unknown; ctx: ExecutionContext; req: CfRequest }}
3133

3234
return {
@@ -37,7 +39,18 @@ framesWithExplicitState(async (ctx) => {
3739
const framesWithExplicitStateAndEnv = createFrames<{ test: boolean }, { secret: string }>({});
3840
framesWithExplicitStateAndEnv(async (ctx) => {
3941
ctx.state satisfies { test: boolean };
40-
ctx satisfies { initialState?: { test: boolean }; message?: any, pressedButton?: any; request: Request; };
42+
ctx satisfies { initialState?: { test: boolean }; message?: unknown, pressedButton?: unknown; request: Request; };
43+
ctx satisfies { cf: { env: { secret: string }; ctx: ExecutionContext; req: CfRequest }}
44+
45+
return {
46+
image: 'http://test.png',
47+
};
48+
}) satisfies ExportedHandlerFetchHandler<{ secret: string }>;
49+
50+
const framesWithExplicitStateAndEnvNoPromiseHandler = createFrames<{ test: boolean }, { secret: string }>({});
51+
framesWithExplicitStateAndEnvNoPromiseHandler((ctx) => {
52+
ctx.state satisfies { test: boolean };
53+
ctx satisfies { initialState?: { test: boolean }; message?: unknown, pressedButton?: unknown; request: Request; };
4154
ctx satisfies { cf: { env: { secret: string }; ctx: ExecutionContext; req: CfRequest }}
4255

4356
return {

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { UrlObject } from "url";
1+
import type { UrlObject } from "node:url";
22

33
type PostButtonProps = {
44
/** A 256-byte string which is label of the button */
@@ -63,6 +63,6 @@ export type ButtonProps =
6363
| LinkButtonProps
6464
| TxButtonProps;
6565

66-
export const Button: React.FunctionComponent<ButtonProps> = () => {
66+
export function Button(_: ButtonProps): null {
6767
return null;
68-
};
68+
}

0 commit comments

Comments
 (0)