Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: change eslint configuration #266

Merged
merged 14 commits into from
Apr 3, 2024
Merged
7 changes: 7 additions & 0 deletions .changeset/chilly-parrots-sneeze.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"frames.js": patch
"@frames.js/debugger": patch
"@frames.js/render": patch
---

fix: minor bugs and code cleanup
5 changes: 1 addition & 4 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@
/** @type {import("eslint").Linter.Config} */
module.exports = {
extends: ["@framesjs/eslint-config/library.js"],
parser: "@typescript-eslint/parser",
parserOptions: {
project: true,
},
env: {
jest: true,
},
ignorePatterns: ["**/farcaster/generated/*.ts"],
};
3 changes: 3 additions & 0 deletions .github/workflows/github-actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ jobs:
- name: Install dependencies
run: yarn --frozen-lockfile

- name: Build
run: yarn build:ci

- name: Lint
run: yarn lint

Expand Down
41 changes: 26 additions & 15 deletions packages/debugger/app/components/frame-debugger.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getFrameHtmlHead, getFrameFlattened } from "frames.js";
import { Dispatch, SetStateAction, useEffect, useMemo, useState } from "react";
import React from "react";
import { FrameState, FrameRequest, FrameStackSuccess } from "frames.js/render";
import { FrameState, FrameStackSuccess } from "@frames.js/render";
import { Table, TableBody, TableCell, TableRow } from "@/components/table";
import {
AlertTriangle,
Expand All @@ -10,7 +10,6 @@ import {
HomeIcon,
ListIcon,
LoaderIcon,
MessageCircle,
MessageCircleHeart,
RefreshCwIcon,
XCircle,
Expand Down Expand Up @@ -190,20 +189,22 @@ export function FrameDebugger({

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

const [latestFrame] = frameState.framesStack;

useEffect(() => {
if (!frameState.isLoading) {
// make sure the first frame is open
if (
!openAccordions.includes(
String(frameState.framesStack[0]?.timestamp.getTime())
String(latestFrame?.timestamp.getTime())
)
)
setOpenAccordions((v) => [
...v,
String(frameState.framesStack[0]?.timestamp.getTime()),
String(latestFrame?.timestamp.getTime()),
]);
}
}, [frameState.isLoading]);
}, [frameState.isLoading, latestFrame?.timestamp, openAccordions]);

return (
<div className="flex flex-row items-start p-4 gap-4 bg-slate-50 max-w-full w-full h-full">
Expand All @@ -219,7 +220,6 @@ export function FrameDebugger({
frameState.fetchFrame({
url: frameState?.homeframeUrl,
method: "GET",
request: {},
});
}}
>
Expand All @@ -235,7 +235,6 @@ export function FrameDebugger({
frameState.fetchFrame({
url: frameState?.homeframeUrl,
method: "GET",
request: {},
});
}
}}
Expand All @@ -246,12 +245,21 @@ export function FrameDebugger({
className="flex flex-row gap-3 items-center shadow-sm border"
variant={"outline"}
onClick={() => {
if (frameState?.framesStack[0]?.request) {
frameState.fetchFrame({
url: frameState?.framesStack[0].url,
method: frameState?.framesStack[0].method,
request: frameState.framesStack[0].request,
} as FrameRequest);
const [latestFrame] = frameState.framesStack;

if (latestFrame) {
frameState.fetchFrame(
latestFrame.method === "GET"
? {
method: "GET",
url: latestFrame.url,
}
: {
method: "POST",
request: latestFrame.request,
url: latestFrame.url,
}
);
}
}}
>
Expand All @@ -269,11 +277,14 @@ export function FrameDebugger({
className={`px-4 py-3 flex flex-col gap-2 ${i !== 0 ? "border-t" : "bg-slate-50"} hover:bg-slate-50 w-full`}
key={frameStackItem.timestamp.getTime()}
onClick={() => {
frameState.fetchFrame({
frameState.fetchFrame(frameStackItem.method === 'GET' ? {
method: 'GET',
url: frameStackItem.url,
} : {
url: frameStackItem.url,
method: frameStackItem.method,
request: frameStackItem.request,
} as FrameRequest);
});
}}
>
<span className="flex text-left flex-row w-full">
Expand Down
2 changes: 1 addition & 1 deletion packages/debugger/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export default function App({
}, []);

useEffect(() => {
if (url !== urlInput && url) {
if (url) {
setUrlInput(url);
}
}, [url]);
Expand Down
28 changes: 19 additions & 9 deletions packages/eslint-config/library.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,12 @@ const project = resolve(process.cwd(), "tsconfig.json");

/** @type {import("eslint").Linter.Config} */
module.exports = {
extends: ["eslint:recommended", "prettier", "eslint-config-turbo"],
plugins: ["only-warn"],
globals: {
React: true,
JSX: true,
},
env: {
node: true,
},
extends: [
require.resolve("@vercel/style-guide/eslint/node"),
require.resolve("@vercel/style-guide/eslint/jest-react"),
require.resolve("@vercel/style-guide/eslint/react"),
require.resolve("@vercel/style-guide/eslint/typescript"),
],
settings: {
"import/resolver": {
typescript: {
Expand All @@ -31,4 +28,17 @@ module.exports = {
files: ["*.js?(x)", "*.ts?(x)"],
},
],
rules: {
"@typescript-eslint/consistent-type-definitions": "off",
"@typescript-eslint/require-await": "warn",
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-unnecessary-condition": "warn",
"@typescript-eslint/consistent-type-imports": "error",
"jest/expect-expect": "warn",
"react/jsx-sort-props": "off",
"unicorn/filename-case": "off",
eqeqeq: "off",
"no-await-in-loop": "off",
"no-implicit-coercion": "off",
},
};
2 changes: 2 additions & 0 deletions packages/frames.js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@
"@types/express": "^4.17.21",
"@xmtp/frames-client": "^0.4.3",
"@xmtp/frames-validator": "^0.5.2",
"@xmtp/proto": "3.45.0",
"@xmtp/xmtp-js": "^11.5.0",
"express": "^4.19.1",
"hono": "^4.1.3",
Expand All @@ -262,6 +263,7 @@
"@cloudflare/workers-types": "^4.20240320.1",
"@types/express": "^4.17.21",
"@xmtp/frames-validator": "^0.5.2",
"@xmtp/proto": "3.45.0",
stephancill marked this conversation as resolved.
Show resolved Hide resolved
"next": "^14.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
Expand Down
6 changes: 3 additions & 3 deletions packages/frames.js/src/cloudflare-workers/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ describe("cloudflare workers adapter", () => {

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

return {
image: <span>Test</span>,
buttons: [<lib.Button action="post">Click me</lib.Button>],
buttons: [<lib.Button action="post" key="1">Click me</lib.Button>],
};
});

Expand All @@ -35,7 +35,7 @@ describe("cloudflare workers adapter", () => {
},
});

const handler = frames(async (ctx) => {
const handler = frames((ctx) => {
expect(ctx.state).toEqual({ test: false });

return {
Expand Down
25 changes: 15 additions & 10 deletions packages/frames.js/src/cloudflare-workers/index.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
export { Button, type types } from "../core";
import { createFrames as coreCreateFrames, types } from "../core";
import type { CoreMiddleware } from "../middleware";
import { Buffer } from "node:buffer";
import {
type CloudflareWorkersMiddleware,
cloudflareWorkersMiddleware,
} from "./middleware";
import type { ExportedHandlerFetchHandler } from "@cloudflare/workers-types";
import type { types } from "../core";
import { createFrames as coreCreateFrames } from "../core";
import type {
FramesMiddleware,
FramesRequestHandlerFunction,
JsonValue,
} from "../core/types";
import type { CoreMiddleware } from "../middleware";
import {
type CloudflareWorkersMiddleware,
cloudflareWorkersMiddleware,
} from "./middleware";

export { Button, type types } from "../core";

export { cloudflareWorkersMiddleware } from "./middleware";

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

type DefaultMiddleware<TEnv> = [
Expand All @@ -28,6 +29,7 @@
* Creates Frames instance to use with you Hono server
*
* @example
* ```ts
* import { createFrames, Button } from 'frames.js/cloudflare-workers';
*
* const frames = createFrames();
Expand All @@ -41,8 +43,10 @@
* ],
* };
* });
* ```
*
* @example
* ```ts
* // With custom type for Env and state
* import { createFrames, Button, type types } from 'frames.js/cloudflare-workers';
*
Expand All @@ -67,12 +71,13 @@
* export default {
* fetch,
* } satisfies ExportedHandler;
* ```
*/
export function createFrames<
TState extends JsonValue | undefined = JsonValue | undefined,
TEnv = unknown,
TFramesMiddleware extends
| FramesMiddleware<any, any>[]

Check warning on line 80 in packages/frames.js/src/cloudflare-workers/index.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type

Check warning on line 80 in packages/frames.js/src/cloudflare-workers/index.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
| undefined = undefined,
>(
options?: types.FramesOptions<TState, TFramesMiddleware>
Expand All @@ -80,14 +85,14 @@
TState,
DefaultMiddleware<TEnv>,
TFramesMiddleware,
ExportedHandlerFetchHandler<TEnv, unknown>
ExportedHandlerFetchHandler<TEnv>
> {
return function cloudflareWorkersFramesHandler<
TPerRouteMiddleware extends
| types.FramesMiddleware<any, any>[]

Check warning on line 92 in packages/frames.js/src/cloudflare-workers/index.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type

Check warning on line 92 in packages/frames.js/src/cloudflare-workers/index.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
| undefined = undefined,
>(
handler: types.FrameHandlerFunction<any, any>,

Check warning on line 95 in packages/frames.js/src/cloudflare-workers/index.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type

Check warning on line 95 in packages/frames.js/src/cloudflare-workers/index.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
handlerOptions?: types.FramesRequestHandlerFunctionOptions<TPerRouteMiddleware>
) {
return function handleCloudflareWorkersRequest(req, env, ctx) {
Expand All @@ -107,7 +112,7 @@
return framesHandler(
// @ts-expect-error - req is almost compatible, there are some differences in the types but it mostly fits all the needs
req
) as unknown as ReturnType<ExportedHandlerFetchHandler<unknown>>;
) as unknown as ReturnType<ExportedHandlerFetchHandler>;
};
};
}
4 changes: 2 additions & 2 deletions packages/frames.js/src/cloudflare-workers/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type {
IncomingRequestCfProperties,
Request,
} from "@cloudflare/workers-types";
import type { FramesMiddleware } from "../core/types";
import type { FramesMiddleware, JsonValue } from "../core/types";

type CloudflareWorkersMiddlewareContext<TEnv> = {
/**
Expand Down Expand Up @@ -34,7 +34,7 @@ type CloudflareWorkersMiddlewareOptions<TEnv> = {
};

export type CloudflareWorkersMiddleware<TEnv> = FramesMiddleware<
any,
JsonValue | undefined,
CloudflareWorkersMiddlewareContext<TEnv>
>;

Expand Down
21 changes: 17 additions & 4 deletions packages/frames.js/src/cloudflare-workers/test.types.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { ExecutionContext, Request as CfRequest, ExportedHandlerFetchHandler } from '@cloudflare/workers-types';
import { createFrames, types } from '.';
/* eslint-disable @typescript-eslint/require-await -- we want to test that handler supports async*/
import type { ExecutionContext, Request as CfRequest, ExportedHandlerFetchHandler } from '@cloudflare/workers-types';
import type { types } from '.';
import { createFrames } from '.';

const framesWithoutState = createFrames();
framesWithoutState(async (ctx) => {
Expand All @@ -26,7 +28,7 @@ framesWithInferredState(async (ctx) => {
const framesWithExplicitState = createFrames<{ test: boolean }>({});
framesWithExplicitState(async (ctx) => {
ctx.state satisfies { test: boolean };
ctx satisfies { initialState?: {test: boolean}; message?: any, pressedButton?: any };
ctx satisfies { initialState?: {test: boolean}; message?: unknown, pressedButton?: unknown };
ctx satisfies { cf: { env: unknown; ctx: ExecutionContext; req: CfRequest }}

return {
Expand All @@ -37,7 +39,18 @@ framesWithExplicitState(async (ctx) => {
const framesWithExplicitStateAndEnv = createFrames<{ test: boolean }, { secret: string }>({});
framesWithExplicitStateAndEnv(async (ctx) => {
ctx.state satisfies { test: boolean };
ctx satisfies { initialState?: { test: boolean }; message?: any, pressedButton?: any; request: Request; };
ctx satisfies { initialState?: { test: boolean }; message?: unknown, pressedButton?: unknown; request: Request; };
ctx satisfies { cf: { env: { secret: string }; ctx: ExecutionContext; req: CfRequest }}

return {
image: 'http://test.png',
};
}) satisfies ExportedHandlerFetchHandler<{ secret: string }>;

const framesWithExplicitStateAndEnvNoPromiseHandler = createFrames<{ test: boolean }, { secret: string }>({});
framesWithExplicitStateAndEnvNoPromiseHandler((ctx) => {
ctx.state satisfies { test: boolean };
ctx satisfies { initialState?: { test: boolean }; message?: unknown, pressedButton?: unknown; request: Request; };
ctx satisfies { cf: { env: { secret: string }; ctx: ExecutionContext; req: CfRequest }}

return {
Expand Down
6 changes: 3 additions & 3 deletions packages/frames.js/src/core/components.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { UrlObject } from "url";
import type { UrlObject } from "node:url";

type PostButtonProps = {
/** A 256-byte string which is label of the button */
Expand Down Expand Up @@ -63,6 +63,6 @@ export type ButtonProps =
| LinkButtonProps
| TxButtonProps;

export const Button: React.FunctionComponent<ButtonProps> = () => {
export function Button(_: ButtonProps): null {
return null;
};
}
Loading