From 2b25562753af8c14ff55bb3b3f6c323c6e20d5a5 Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Tue, 26 Mar 2024 12:00:09 +0200 Subject: [PATCH 01/42] fix: @frames/render turbo build --- .changeset/five-mangos-try.md | 5 +++++ packages/frames.js/package.json | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 .changeset/five-mangos-try.md diff --git a/.changeset/five-mangos-try.md b/.changeset/five-mangos-try.md new file mode 100644 index 000000000..d10084d54 --- /dev/null +++ b/.changeset/five-mangos-try.md @@ -0,0 +1,5 @@ +--- +"frames.js": patch +--- + +fix: turbo build diff --git a/packages/frames.js/package.json b/packages/frames.js/package.json index d7dbd53c7..9755f45d0 100644 --- a/packages/frames.js/package.json +++ b/packages/frames.js/package.json @@ -14,7 +14,7 @@ }, "scripts": { "lint": "eslint \"./src/**/*.{ts,tsx}\"", - "build": "NODE_OPTIONS='--max-old-space-size=16384' rimraf ./dist && tsup `find ./src -type f \\( -regex '.*\\.tsx*' -a -not -regex '.*\\.test\\.tsx*' \\)` --format cjs,esm --dts", + "build": "NODE_OPTIONS='--max-old-space-size=16384' tsup `find ./src -type f \\( -regex '.*\\.tsx*' -a -not -regex '.*\\.test\\.tsx*' \\)` --format cjs,esm --dts", "dev": "npm run build -- --watch", "test:watch": "jest --watch", "update:proto": "curl https://raw.githubusercontent.com/farcasterxyz/hub-monorepo/main/packages/core/src/protobufs/generated/message.ts -o src/farcaster/generated/message.ts" @@ -235,4 +235,4 @@ "protobufjs": "^7.2.6", "viem": "^2.7.8" } -} +} \ No newline at end of file From 4836b7f398c2e5ebe7300d15e20f69f169b3bba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kvasnic=CC=8Ca=CC=81k?= Date: Tue, 26 Mar 2024 11:58:01 +0100 Subject: [PATCH 02/42] build: lint, typecheck and test code --- .github/workflows/github-actions.yml | 50 ++++++++++++++++++++++++++++ jest.config.js | 4 +++ package.json | 4 ++- packages/frames.js/package.json | 1 + yarn.lock | 27 +++++++++++++++ 5 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/github-actions.yml create mode 100644 jest.config.js diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml new file mode 100644 index 000000000..861e6b214 --- /dev/null +++ b/.github/workflows/github-actions.yml @@ -0,0 +1,50 @@ +name: Frames.js Actions + +on: + push: + branches: + - main + - dev + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + initialize: + timeout-minutes: 5 + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v4 + with: + fetch-depth: 2 + + - name: Setup Node.js environment + uses: actions/setup-node@v4 + with: + node-version: 18 + cache: "yarn" + + - name: Install dependencies + run: yarn --frozen-lockfile + + lint: + needs: [initialize] + steps: + - name: Lint + run: yarn lint + + typecheck: + needs: [initialize] + steps: + - name: Typecheck + run: yarn build:ci + + test: + need: [lint, typecheck] + timeout-minutes: 10 + steps: + - name: Unit Tests + run: yarn test:ci diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 000000000..47413007a --- /dev/null +++ b/jest.config.js @@ -0,0 +1,4 @@ +/** @type {import('jest').Config} */ +module.exports = { + projects: ["/packages/frames.js/jest.config.js"], +}; diff --git a/package.json b/package.json index 0509b1517..3a20560e2 100644 --- a/package.json +++ b/package.json @@ -3,11 +3,13 @@ "private": true, "scripts": { "build": "turbo build", + "build:ci": "turbo build --filter=!debugger", "dev": "FJS_MONOREPO=true turbo dev --filter=framesjs-starter... --filter=debugger...", "dev:custom-redirects": "turbo dev --filter=custom-redirects...", "dev:utils-starter": "turbo dev --filter=utils-starter...", "dev:all": "turbo dev", "lint": "turbo lint", + "test:ci": "jest --ci", "test": "cd ./packages/frames.js && npm run test:watch", "publish-packages": "turbo run build lint && changeset version && changeset publish && git push --follow-tags origin main", "publish-canary": "turbo run build lint && cd ./packages/frames.js && yarn publish --tag canary && git push --follow-tags origin main", @@ -36,4 +38,4 @@ "packages/*" ], "version": "0.3.0-canary.0" -} \ No newline at end of file +} diff --git a/packages/frames.js/package.json b/packages/frames.js/package.json index d7dbd53c7..a7a5b1ff5 100644 --- a/packages/frames.js/package.json +++ b/packages/frames.js/package.json @@ -212,6 +212,7 @@ "devDependencies": { "@open-frames/types": "^0.0.6", "@remix-run/node": "^2.8.1", + "@types/supertest": "^6.0.2", "@types/express": "^4.17.21", "@xmtp/frames-client": "^0.4.3", "@xmtp/frames-validator": "^0.5.2", diff --git a/yarn.lock b/yarn.lock index cbe58a918..1782f060c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2943,6 +2943,11 @@ resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.6.0.tgz#eac397f28bf1d6ae0ae081363eca2f425bedf0d5" integrity sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA== +"@types/cookiejar@^2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@types/cookiejar/-/cookiejar-2.1.5.tgz#14a3e83fa641beb169a2dd8422d91c3c345a9a78" + integrity sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q== + "@types/debug@^4.0.0", "@types/debug@^4.1.7": version "4.1.12" resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" @@ -3080,6 +3085,11 @@ resolved "https://registry.yarnpkg.com/@types/mdx/-/mdx-2.0.11.tgz#21f4c166ed0e0a3a733869ba04cd8daea9834b8e" integrity sha512-HM5bwOaIQJIQbAYfax35HCKxx7a3KrK3nBtIqJgSOitivTD1y3oW9P3rxY9RkXYPUk7y/AjAohfHKmFpGE79zw== +"@types/methods@^1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@types/methods/-/methods-1.1.4.tgz#d3b7ac30ac47c91054ea951ce9eed07b1051e547" + integrity sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ== + "@types/mime@*": version "3.0.4" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.4.tgz#2198ac274de6017b44d941e00261d5bc6a0e0a45" @@ -3199,6 +3209,23 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== +"@types/superagent@^8.1.0": + version "8.1.6" + resolved "https://registry.yarnpkg.com/@types/superagent/-/superagent-8.1.6.tgz#e660543b1a4b7c7473caec4799de87ff68216270" + integrity sha512-yzBOv+6meEHSzV2NThYYOA6RtqvPr3Hbob9ZLp3i07SH27CrYVfm8CrF7ydTmidtelsFiKx2I4gZAiAOamGgvQ== + dependencies: + "@types/cookiejar" "^2.1.5" + "@types/methods" "^1.1.4" + "@types/node" "*" + +"@types/supertest@^6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@types/supertest/-/supertest-6.0.2.tgz#2af1c466456aaf82c7c6106c6b5cbd73a5e86588" + integrity sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg== + dependencies: + "@types/methods" "^1.1.4" + "@types/superagent" "^8.1.0" + "@types/trusted-types@^2.0.2": version "2.0.7" resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11" From 6b57b185f6cf497660886f09f6309227b20de2d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kvasnic=CC=8Ca=CC=81k?= Date: Tue, 26 Mar 2024 11:59:48 +0100 Subject: [PATCH 03/42] fix: add missing runs-on --- .github/workflows/github-actions.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index 861e6b214..bb74793d2 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -32,18 +32,21 @@ jobs: lint: needs: [initialize] + runs-on: ubuntu-latest steps: - name: Lint run: yarn lint typecheck: needs: [initialize] + runs-on: ubuntu-latest steps: - name: Typecheck run: yarn build:ci test: need: [lint, typecheck] + runs-on: ubuntu-latest timeout-minutes: 10 steps: - name: Unit Tests From f3e9d1fa2e50e67b3025ecba3ce6d44f8ae23474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kvasnic=CC=8Ca=CC=81k?= Date: Tue, 26 Mar 2024 12:01:03 +0100 Subject: [PATCH 04/42] fix: typo --- .github/workflows/github-actions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index bb74793d2..aa2251ce1 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -45,7 +45,7 @@ jobs: run: yarn build:ci test: - need: [lint, typecheck] + needs: [lint, typecheck] runs-on: ubuntu-latest timeout-minutes: 10 steps: From 2db46159fc63922afbb1e94a676043adba65223d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kvasnic=CC=8Ca=CC=81k?= Date: Tue, 26 Mar 2024 12:09:49 +0100 Subject: [PATCH 05/42] build: checkout and install deps in all jobs --- .github/workflows/github-actions.yml | 38 ++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index aa2251ce1..a222df854 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -18,8 +18,6 @@ jobs: steps: - name: Check out code uses: actions/checkout@v4 - with: - fetch-depth: 2 - name: Setup Node.js environment uses: actions/setup-node@v4 @@ -34,6 +32,18 @@ jobs: needs: [initialize] runs-on: ubuntu-latest steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Setup Node.js environment + uses: actions/setup-node@v4 + with: + node-version: 18 + cache: "yarn" + + - name: Install dependencies + run: yarn --frozen-lockfile + - name: Lint run: yarn lint @@ -41,6 +51,18 @@ jobs: needs: [initialize] runs-on: ubuntu-latest steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Setup Node.js environment + uses: actions/setup-node@v4 + with: + node-version: 18 + cache: "yarn" + + - name: Install dependencies + run: yarn --frozen-lockfile + - name: Typecheck run: yarn build:ci @@ -49,5 +71,17 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Setup Node.js environment + uses: actions/setup-node@v4 + with: + node-version: 18 + cache: "yarn" + + - name: Install dependencies + run: yarn --frozen-lockfile + - name: Unit Tests run: yarn test:ci From b1e9261436996093d7e2dd8363ece40bd04dd85a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kvasnic=CC=8Ca=CC=81k?= Date: Tue, 26 Mar 2024 12:15:26 +0100 Subject: [PATCH 06/42] build: do not build starter and docs --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3a20560e2..bb93324a6 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "private": true, "scripts": { "build": "turbo build", - "build:ci": "turbo build --filter=!debugger", + "build:ci": "turbo build --filter=!debugger --filter=!framesjs-starter --filter=!utils-starter --filter=!docs", "dev": "FJS_MONOREPO=true turbo dev --filter=framesjs-starter... --filter=debugger...", "dev:custom-redirects": "turbo dev --filter=custom-redirects...", "dev:utils-starter": "turbo dev --filter=utils-starter...", From d2d6e00a5ddb5cb7e6d9fcbf6bf81b816d85110c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kvasnic=CC=8Ca=CC=81k?= Date: Tue, 26 Mar 2024 12:28:41 +0100 Subject: [PATCH 07/42] test: fix assertions --- .../frames.js/src/next/getCurrentUrl.test.ts | 68 +++++++++++++++++-- 1 file changed, 61 insertions(+), 7 deletions(-) diff --git a/packages/frames.js/src/next/getCurrentUrl.test.ts b/packages/frames.js/src/next/getCurrentUrl.test.ts index a91f125ac..dd1008692 100644 --- a/packages/frames.js/src/next/getCurrentUrl.test.ts +++ b/packages/frames.js/src/next/getCurrentUrl.test.ts @@ -1,6 +1,17 @@ +/* eslint-disable turbo/no-undeclared-env-vars */ import { getCurrentUrl } from "./getCurrentUrl"; describe("getCurrentUrl", () => { + beforeEach(() => { + // @ts-expect-error + process.env.NODE_ENV = "test"; + }); + + afterEach(() => { + delete process.env.VERCEL_URL; + delete process.env.APP_URL; + }); + it("works with relative url property", () => { expect( getCurrentUrl({ @@ -8,8 +19,8 @@ describe("getCurrentUrl", () => { headers: { host: "localhost", }, - } as unknown as Request) - ).toEqual(new URL("http://localhost/test")); + } as unknown as Request)?.toString() + ).toEqual("http://localhost/test"); }); it("takes value from process.env.VERCEL_URL if available", () => { @@ -21,13 +32,56 @@ describe("getCurrentUrl", () => { headers: { host: "localhost", }, - } as unknown as Request) - ).toEqual(new URL("http://test.com/")); + } as unknown as Request)?.toString() + ).toEqual("http://test.com/test"); + }); + + it("takes value from process.env.VERCEL_URL and uses https if NODE_ENV=production if available", () => { + process.env.VERCEL_URL = "test.com"; + // @ts-expect-error + process.env.NODE_ENV = "production"; + + expect( + getCurrentUrl({ + url: "/test", + headers: { + host: "localhost", + }, + } as unknown as Request)?.toString() + ).toEqual("https://test.com/test"); + }); + + it("takes value from process.env.APP_URL if available", () => { + process.env.APP_URL = "app.com"; + + expect( + getCurrentUrl({ + url: "/test", + headers: { + host: "localhost", + }, + } as unknown as Request)?.toString() + ).toEqual("http://app.com/test"); + }); + + it("takes value from process.env.APP_URL and uses https if NODE_ENV=production if available", () => { + process.env.APP_URL = "test.com"; + // @ts-expect-error + process.env.NODE_ENV = "production"; + + expect( + getCurrentUrl({ + url: "/test", + headers: { + host: "localhost", + }, + } as unknown as Request)?.toString() + ).toEqual("https://test.com/test"); }); it("supports proper url in Request object", () => { - expect(getCurrentUrl(new Request("http://localhost/test"))).toEqual( - new URL("http://localhost/test") - ); + expect( + getCurrentUrl(new Request("http://localhost/test"))?.toString() + ).toEqual("http://localhost/test"); }); }); From 1941701103bec14cf987774390c8874acd336183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kvasnic=CC=8Ca=CC=81k?= Date: Tue, 26 Mar 2024 12:37:49 +0100 Subject: [PATCH 08/42] chore: deprecate old next api --- packages/frames.js/src/next/server.tsx | 49 ++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/packages/frames.js/src/next/server.tsx b/packages/frames.js/src/next/server.tsx index f689e0b7a..20ffd0dfd 100644 --- a/packages/frames.js/src/next/server.tsx +++ b/packages/frames.js/src/next/server.tsx @@ -47,7 +47,12 @@ export type FrameElementType = | typeof FrameImage | typeof FrameInput; -/** validates a frame action message payload signature, @returns message, throws an Error on failure */ +/** + * validates a frame action message payload signature, + * @returns message, throws an Error on failure + * + * @deprecated please upgrade to new API, see https://framesjs.org/guides/security + */ export async function validateActionSignature( frameActionPayload: FrameActionPayload | null, options?: HubHttpUrlOptions @@ -80,6 +85,8 @@ export async function validateActionSignature( /** Convenience wrapper around `framesjs.getFrameMessage` that accepts a null for payload body. * Returns a `FrameActionData` object from the message trusted data. (e.g. button index, input text). The `fetchHubContext` option (default: true) determines whether to validate and fetch other metadata from hubs. * If `isValid` is false, the message should not be trusted. + * + * @deprecated please upgrade to new API, see https://framesjs.org/reference/core/next */ export async function getFrameMessage( frameActionPayload: FrameActionPayload | null, @@ -109,7 +116,10 @@ export async function getFrameMessage( return result; } -/** deserializes a `PreviousFrame` from url searchParams, fetching headers automatically from nextjs, @returns PreviousFrame */ +/** + * deserializes a `PreviousFrame` from url searchParams, fetching headers automatically from nextjs, @returns PreviousFrame + * @deprecated please upgrade to new API, see https://framesjs.org/reference/core/next. + */ export function getPreviousFrame( searchParams: NextServerPageProps["searchParams"] ): PreviousFrame { @@ -130,7 +140,10 @@ export function getPreviousFrame( return createPreviousFrame(parseFrameParams(searchParams), headersList); } -/** @returns PreviousFrame by combining headers and previousFrames from params */ +/** + * @deprecated please upgrade to new API, see https://framesjs.org/reference/core/next + * @returns PreviousFrame by combining headers and previousFrames from params + */ export function createPreviousFrame( previousFrameFromParams: Pick< PreviousFrame, @@ -144,7 +157,11 @@ export function createPreviousFrame( }; } -/** deserializes data stored in the url search params and @returns a Partial PreviousFrame object */ +/** + * @deprecated please upgrade to new API, see https://framesjs.org/reference/core/next + * + * deserializes data stored in the url search params and @returns a Partial PreviousFrame object + */ export function parseFrameParams( searchParams: NextServerPageProps["searchParams"] ): Pick< @@ -186,6 +203,8 @@ export function parseFrameParams( * @param initialState the initial state to use if there was no previous action * @param initializerArg the previousFrame object to use to initialize the state * @returns An array of [State, Dispatch] where State is your reducer state, and dispatch is a function that doesn't do anything atm + * + * @deprecated please upgrade to new API, see https://framesjs.org/reference/core/next. */ export function useFramesReducer( reducer: FrameReducer, @@ -242,6 +261,8 @@ function toUrl(req: NextRequest) { * It handles all the redirecting for you, correctly, based on the props defined by the Frame that triggered the user action. * @param req a `NextRequest` object from `next/server` (Next.js app router server components) * @returns NextResponse + * + * @deprecated please upgrade to new API, see https://framesjs.org/reference/core/next. */ export async function POST( req: NextRequest, @@ -373,6 +394,8 @@ function isElementFrameInput( } /** + * @deprecated please upgrade to new API, see https://framesjs.org/reference/core/next + * * A React functional component that Wraps a Frame and processes it, validating certain properties of the Frames spec, as well as adding other props. It also generates the postUrl. * It throws an error if the Frame is invalid, which can be caught by using an error boundary. * @param param0 @@ -570,7 +593,11 @@ export function FrameContainer({ ); } -/** Renders a 'fc:frame:button', must be used inside a `FrameContainer` */ +/** + * Renders a 'fc:frame:button', must be used inside a `FrameContainer` + * + * @deprecated please upgrade to new API, see https://framesjs.org/reference/core/next + */ export function FrameButton(props: FrameButtonProvidedProps) { return null; } @@ -603,7 +630,11 @@ function FFrameButtonShim({ ); } -/** Render a 'fc:frame:input:text', must be used inside a */ +/** + * Render a 'fc:frame:input:text', must be used inside a + * + * @deprecated please upgrade to new API, see https://framesjs.org/reference/core/next + */ export function FrameInput({ text }: { text: string }) { return ( <> @@ -612,7 +643,11 @@ export function FrameInput({ text }: { text: string }) { ); } -/** Render a 'fc:frame:image', must be used inside a */ +/** + * Render a 'fc:frame:image', must be used inside a + * + * @deprecated please upgrade to new API, see https://framesjs.org/reference/core/next + */ export async function FrameImage( props: { /** 'fc:frame:aspect_ratio' (defaults to 1:91) */ From 143487915cbad6bc5dae169eac4fcf56b0ab7346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kvasnic=CC=8Ca=CC=81k?= Date: Tue, 26 Mar 2024 12:39:38 +0100 Subject: [PATCH 09/42] chore: add changeset --- .changeset/olive-kangaroos-talk.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/olive-kangaroos-talk.md diff --git a/.changeset/olive-kangaroos-talk.md b/.changeset/olive-kangaroos-talk.md new file mode 100644 index 000000000..8b3afb2a4 --- /dev/null +++ b/.changeset/olive-kangaroos-talk.md @@ -0,0 +1,5 @@ +--- +"frames.js": minor +--- + +chore: deprecate old Next.js api From d9032bbacfbec060179c96f4de7967c06562c615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kvasnic=CC=8Ca=CC=81k?= Date: Tue, 5 Mar 2024 18:55:18 +0100 Subject: [PATCH 10/42] feat: basic create-frames cli tool feat: add next simple template fix: ignore some files when copying templates chore: remove fs-extra dep chore: add changeset remove comment chore: improve dependencies installation and run app in debugger by default chore: improve debugger hub comment chore: document installation chore: remove debug hub usage in case of production build chore: add two more examples based on starters chore: update to new dep --- .changeset/smooth-bugs-admire.md | 5 + .scripts/package.json | 3 + .scripts/prepare-create-frames.js | 33 ++ docs/pages/index.mdx | 30 +- package.json | 7 +- packages/create-frames/.gitignore | 1 + packages/create-frames/.npmignore | 1 + packages/create-frames/README.md | 48 +++ packages/create-frames/bin.js | 30 ++ packages/create-frames/create.js | 135 +++++++ packages/create-frames/package.json | 22 ++ packages/create-frames/tsconfig.json | 30 ++ packages/create-frames/utils/getTemplates.js | 10 + .../utils/packageManagerRunCommand.js | 16 + .../next-starter-with-examples/.env.sample | 17 + .../next-starter-with-examples/.eslintrc.js | 5 + .../next-starter-with-examples/.gitignore | 39 ++ .../next-starter-with-examples/CHANGELOG.md | 153 ++++++++ .../next-starter-with-examples/README.md | 40 +++ .../next-starter-with-examples/app/debug.ts | 15 + .../app/examples/custom-hub/frames/route.ts | 1 + .../app/examples/custom-hub/page.tsx | 117 ++++++ .../app/examples/mint-button/frames/route.ts | 1 + .../app/examples/mint-button/page.tsx | 89 +++++ .../app/examples/multi-page/frames/route.ts | 1 + .../app/examples/multi-page/page.tsx | 61 ++++ .../examples/multi-protocol/frames/route.ts | 1 + .../app/examples/multi-protocol/page.tsx | 83 +++++ .../app/examples/page.tsx | 50 +++ .../app/examples/slow-request/README.md | 6 + .../app/examples/slow-request/frames/route.ts | 1 + .../app/examples/slow-request/page.tsx | 178 ++++++++++ .../examples/slow-request/slow-fetch/route.ts | 53 +++ .../examples/slow-request/slow-fetch/types.ts | 15 + .../app/examples/transaction/frames/route.ts | 1 + .../app/examples/transaction/page.tsx | 54 +++ .../app/examples/transaction/txdata/route.ts | 17 + .../app/examples/user-data/frames/route.ts | 1 + .../app/examples/user-data/page.tsx | 93 +++++ .../app/frames/route.ts | 1 + .../app/globals.css | 76 ++++ .../next-starter-with-examples/app/layout.tsx | 20 ++ .../next-starter-with-examples/app/page.tsx | 114 ++++++ .../next-starter-with-examples/app/utils.ts | 9 + .../next.config.mjs | 19 + .../next-starter-with-examples/package.json | 42 +++ .../postcss.config.js | 6 + .../public/Inter-Regular.ttf | Bin 0 -> 310252 bytes .../public/next.svg | 1 + .../public/vercel.svg | 1 + .../tailwind.config.ts | 90 +++++ .../next-starter-with-examples/tsconfig.json | 47 +++ templates/next-utils-starter/.env.sample | 1 + templates/next-utils-starter/.eslintrc.js | 5 + templates/next-utils-starter/.gitignore | 36 ++ templates/next-utils-starter/CHANGELOG.md | 60 ++++ templates/next-utils-starter/README.md | 30 ++ .../app/api/frame/route.tsx | 46 +++ templates/next-utils-starter/app/constants.ts | 6 + templates/next-utils-starter/app/favicon.ico | Bin 0 -> 8267 bytes templates/next-utils-starter/app/layout.tsx | 33 ++ .../next-utils-starter/app/page.module.css | 335 ++++++++++++++++++ templates/next-utils-starter/app/page.tsx | 3 + templates/next-utils-starter/next.config.js | 2 + templates/next-utils-starter/package.json | 31 ++ templates/next-utils-starter/public/image.png | Bin 0 -> 88230 bytes .../next-utils-starter/public/image_frame.png | Bin 0 -> 22827 bytes .../public/image_frame_flipped.png | Bin 0 -> 78712 bytes templates/next-utils-starter/tsconfig.json | 39 ++ templates/next/.gitignore | 36 ++ templates/next/README.md | 17 + templates/next/app/frames/route.tsx | 54 +++ templates/next/app/globals.css | 11 + templates/next/app/layout.tsx | 22 ++ templates/next/app/page.tsx | 17 + templates/next/next.config.js | 4 + templates/next/package.json | 26 ++ templates/next/public/next.svg | 1 + templates/next/public/vercel.svg | 1 + templates/next/tsconfig.json | 26 ++ turbo.json | 1 + yarn.lock | 138 +++++++- 82 files changed, 2853 insertions(+), 17 deletions(-) create mode 100644 .changeset/smooth-bugs-admire.md create mode 100644 .scripts/package.json create mode 100644 .scripts/prepare-create-frames.js create mode 100644 packages/create-frames/.gitignore create mode 100644 packages/create-frames/.npmignore create mode 100644 packages/create-frames/README.md create mode 100755 packages/create-frames/bin.js create mode 100644 packages/create-frames/create.js create mode 100644 packages/create-frames/package.json create mode 100644 packages/create-frames/tsconfig.json create mode 100644 packages/create-frames/utils/getTemplates.js create mode 100644 packages/create-frames/utils/packageManagerRunCommand.js create mode 100644 templates/next-starter-with-examples/.env.sample create mode 100644 templates/next-starter-with-examples/.eslintrc.js create mode 100644 templates/next-starter-with-examples/.gitignore create mode 100644 templates/next-starter-with-examples/CHANGELOG.md create mode 100644 templates/next-starter-with-examples/README.md create mode 100644 templates/next-starter-with-examples/app/debug.ts create mode 100644 templates/next-starter-with-examples/app/examples/custom-hub/frames/route.ts create mode 100644 templates/next-starter-with-examples/app/examples/custom-hub/page.tsx create mode 100644 templates/next-starter-with-examples/app/examples/mint-button/frames/route.ts create mode 100644 templates/next-starter-with-examples/app/examples/mint-button/page.tsx create mode 100644 templates/next-starter-with-examples/app/examples/multi-page/frames/route.ts create mode 100644 templates/next-starter-with-examples/app/examples/multi-page/page.tsx create mode 100644 templates/next-starter-with-examples/app/examples/multi-protocol/frames/route.ts create mode 100644 templates/next-starter-with-examples/app/examples/multi-protocol/page.tsx create mode 100644 templates/next-starter-with-examples/app/examples/page.tsx create mode 100644 templates/next-starter-with-examples/app/examples/slow-request/README.md create mode 100644 templates/next-starter-with-examples/app/examples/slow-request/frames/route.ts create mode 100644 templates/next-starter-with-examples/app/examples/slow-request/page.tsx create mode 100644 templates/next-starter-with-examples/app/examples/slow-request/slow-fetch/route.ts create mode 100644 templates/next-starter-with-examples/app/examples/slow-request/slow-fetch/types.ts create mode 100644 templates/next-starter-with-examples/app/examples/transaction/frames/route.ts create mode 100644 templates/next-starter-with-examples/app/examples/transaction/page.tsx create mode 100644 templates/next-starter-with-examples/app/examples/transaction/txdata/route.ts create mode 100644 templates/next-starter-with-examples/app/examples/user-data/frames/route.ts create mode 100644 templates/next-starter-with-examples/app/examples/user-data/page.tsx create mode 100644 templates/next-starter-with-examples/app/frames/route.ts create mode 100644 templates/next-starter-with-examples/app/globals.css create mode 100644 templates/next-starter-with-examples/app/layout.tsx create mode 100644 templates/next-starter-with-examples/app/page.tsx create mode 100644 templates/next-starter-with-examples/app/utils.ts create mode 100644 templates/next-starter-with-examples/next.config.mjs create mode 100644 templates/next-starter-with-examples/package.json create mode 100644 templates/next-starter-with-examples/postcss.config.js create mode 100644 templates/next-starter-with-examples/public/Inter-Regular.ttf create mode 100644 templates/next-starter-with-examples/public/next.svg create mode 100644 templates/next-starter-with-examples/public/vercel.svg create mode 100644 templates/next-starter-with-examples/tailwind.config.ts create mode 100644 templates/next-starter-with-examples/tsconfig.json create mode 100644 templates/next-utils-starter/.env.sample create mode 100644 templates/next-utils-starter/.eslintrc.js create mode 100644 templates/next-utils-starter/.gitignore create mode 100644 templates/next-utils-starter/CHANGELOG.md create mode 100644 templates/next-utils-starter/README.md create mode 100644 templates/next-utils-starter/app/api/frame/route.tsx create mode 100644 templates/next-utils-starter/app/constants.ts create mode 100644 templates/next-utils-starter/app/favicon.ico create mode 100644 templates/next-utils-starter/app/layout.tsx create mode 100644 templates/next-utils-starter/app/page.module.css create mode 100644 templates/next-utils-starter/app/page.tsx create mode 100644 templates/next-utils-starter/next.config.js create mode 100644 templates/next-utils-starter/package.json create mode 100644 templates/next-utils-starter/public/image.png create mode 100644 templates/next-utils-starter/public/image_frame.png create mode 100644 templates/next-utils-starter/public/image_frame_flipped.png create mode 100644 templates/next-utils-starter/tsconfig.json create mode 100644 templates/next/.gitignore create mode 100644 templates/next/README.md create mode 100644 templates/next/app/frames/route.tsx create mode 100644 templates/next/app/globals.css create mode 100644 templates/next/app/layout.tsx create mode 100644 templates/next/app/page.tsx create mode 100644 templates/next/next.config.js create mode 100644 templates/next/package.json create mode 100644 templates/next/public/next.svg create mode 100644 templates/next/public/vercel.svg create mode 100644 templates/next/tsconfig.json diff --git a/.changeset/smooth-bugs-admire.md b/.changeset/smooth-bugs-admire.md new file mode 100644 index 000000000..a26c2a427 --- /dev/null +++ b/.changeset/smooth-bugs-admire.md @@ -0,0 +1,5 @@ +--- +"create-frames": minor +--- + +feat: introduce cli tool to bootstrap projects from templates diff --git a/.scripts/package.json b/.scripts/package.json new file mode 100644 index 000000000..aead43de3 --- /dev/null +++ b/.scripts/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} \ No newline at end of file diff --git a/.scripts/prepare-create-frames.js b/.scripts/prepare-create-frames.js new file mode 100644 index 000000000..16dc6d54e --- /dev/null +++ b/.scripts/prepare-create-frames.js @@ -0,0 +1,33 @@ +/** + * This script is used to prepare create-frames package for publishing. + * + * It copies the templates directory to the root of the package so that it can be used by the create-frames package. + */ + +import { dirname, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import glob from "fast-glob"; +import { cpSync, renameSync, rmSync } from 'node:fs'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + + +rmSync(resolve(__dirname, "../packages/create-frames/templates"), { force: true, recursive: true }); + +cpSync( + resolve(__dirname, "../templates"), + resolve(__dirname, "../packages/create-frames/templates"), + { + recursive: true, + filter: (src) => !/(node_modules|\.turbo|\.next|next-env\.d\.ts)/.test(src), + } +); + +const dotfiles = await glob( + resolve(__dirname, "../packages/create-frames/templates/**/.*") +); + +// rename dotfiles to use underscore instead of dot so we can publish them to npm as is +for (const doftile of dotfiles) { + renameSync(doftile, doftile.replace("/.", "/_")); +} diff --git a/docs/pages/index.mdx b/docs/pages/index.mdx index 570504f3f..2dfefd0a2 100644 --- a/docs/pages/index.mdx +++ b/docs/pages/index.mdx @@ -7,7 +7,7 @@ import { HomePage } from "vocs/components";

frames.js

- + **frames.js** is the fastest way to make Frames. @@ -18,6 +18,12 @@ import { HomePage } from "vocs/components"; GitHub + + Quickstart + + + GitHub +
@@ -31,15 +37,27 @@ import { HomePage } from "vocs/components"; # Quickstart -## 1. Clone the frames.js starter template (with local debugger) +## Bootstrap the project from template using the CLI tool -Run to clone the starter into a new folder called `framesjs-starter` +Run one of the commands below based on your preferred package manager and then follow the steps in the terminal. -```bash -npx degit github:framesjs/frames.js/examples/framesjs-starter#main framesjs-starter +### Using npm + +```sh +npm init frames +``` + +### Using yarn + +```sh +yarn create frames ``` -or [clone from github](https://github.com/framesjs/frames.js/tree/main/examples/framesjs-starter) +### Using pnpm + +```sh +pnpm create frames +``` ## Alternatively, add frames.js to your existing project manually diff --git a/package.json b/package.json index bb93324a6..a906279e7 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "framesjs-monorepo", "private": true, "scripts": { - "build": "turbo build", + "build": "turbo build && node ./.scripts/prepare-create-frames.js", "build:ci": "turbo build --filter=!debugger --filter=!framesjs-starter --filter=!utils-starter --filter=!docs", "dev": "FJS_MONOREPO=true turbo dev --filter=framesjs-starter... --filter=debugger...", "dev:custom-redirects": "turbo dev --filter=custom-redirects...", @@ -23,9 +23,11 @@ "@framesjs/typescript-config": "*", "@jest/globals": "^29.7.0", "@types/jest": "^29.5.11", + "fast-glob": "^3.3.2", "jest": "^29.7.0", "nock": "beta", "prettier": "^3.1.1", + "rimraf": "^5.0.5", "turbo": "^1.12.2" }, "engines": { @@ -35,7 +37,8 @@ "workspaces": [ "docs", "examples/*", - "packages/*" + "packages/*", + "templates/*" ], "version": "0.3.0-canary.0" } diff --git a/packages/create-frames/.gitignore b/packages/create-frames/.gitignore new file mode 100644 index 000000000..f10e14abd --- /dev/null +++ b/packages/create-frames/.gitignore @@ -0,0 +1 @@ +templates \ No newline at end of file diff --git a/packages/create-frames/.npmignore b/packages/create-frames/.npmignore new file mode 100644 index 000000000..eb61e78f0 --- /dev/null +++ b/packages/create-frames/.npmignore @@ -0,0 +1 @@ +!templates \ No newline at end of file diff --git a/packages/create-frames/README.md b/packages/create-frames/README.md new file mode 100644 index 000000000..2f5df6d52 --- /dev/null +++ b/packages/create-frames/README.md @@ -0,0 +1,48 @@ +# Create Frames.js app + +Create a new Frames.js app with a single command using predefined templates. + +## Creating a project + +### Using npm + +```sh +npm init frames +``` + +### Using yarn + +```sh +yarn create frames +``` + +### Using pnpm + +```sh +pnpm create frames +``` + +## Installing globally (optional) and running from terminal + +You can also install this package globally and run it from your terminal. + +### Using npm + +```sh +npm install -g create-frames +create-frames +``` + +### Using yarn + +```sh +yarn global add create-frames +create-frames +``` + +### Using pnpm + +```sh +pnpm add -g create-frames +create-frames +``` diff --git a/packages/create-frames/bin.js b/packages/create-frames/bin.js new file mode 100755 index 000000000..e9b1d9161 --- /dev/null +++ b/packages/create-frames/bin.js @@ -0,0 +1,30 @@ +#!/usr/bin/env node +import yargs from "yargs"; +import { hideBin } from "yargs/helpers"; +import { getTemplates } from "./utils/getTemplates.js"; +import { create } from "./create.js"; + +// use only default command +yargs(hideBin(process.argv)) + .scriptName("create-frames") + .usage("Usage: $0 [options]") + .command( + "$0", + "Create a new project", + { + name: { + alias: "n", + describe: "Name of the project", + type: "string", + }, + template: { + alias: "t", + describe: "Choose a template for the project", + choices: getTemplates(), + }, + }, + (args) => { + create(args); + } + ) + .parse(); diff --git a/packages/create-frames/create.js b/packages/create-frames/create.js new file mode 100644 index 000000000..e99674800 --- /dev/null +++ b/packages/create-frames/create.js @@ -0,0 +1,135 @@ +import { intro, log, outro, select, confirm, text } from "@clack/prompts"; +import { getTemplates } from "./utils/getTemplates.js"; +import { dirname, relative, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { spawnSync } from "node:child_process"; +import ignore from "ignore"; +import pc from "picocolors"; +import { detect as detectPackageManager } from "detect-package-manager"; +import { + cpSync, + readFileSync, + readdirSync, + renameSync, + writeFileSync, +} from "node:fs"; +import { packageManagerRunCommand } from "./utils/packageManagerRunCommand.js"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +/** + * + * @param {import('yargs').ArgumentsCamelCase<{ t?: string, n?: string }>} params + */ +export async function create(params) { + if (params.$0 !== "create-frames") { + throw new Error("Invalid command"); + } + + intro("Welcome to frames.js"); + + // if there is no -n argument (name, ask for the name of new project) + let projectName = + params.n || + (await text({ + message: "Enter the name of your project", + placeholder: "my-frames-app", + validate(input) { + if (!input) { + return "Project name is required"; + } + + return; + }, + })); + + const destDir = resolve(process.cwd(), projectName); + + const template = + params.t || + (await select({ + message: "Choose a template for the project", + options: getTemplates().map((template) => ({ + name: template, + value: template, + })), + defaultValue: "next", + validate(input) { + if (!input) { + return "Template is required"; + } + + return; + }, + })); + + const templateDir = resolve(__dirname, "./templates", template); + const ignoredPatterns = readFileSync( + resolve(templateDir, "_gitignore"), + "utf-8" + ); + const ignored = ignore().add(ignoredPatterns); + + cpSync(templateDir, destDir, { + force: true, + recursive: true, + filter(src) { + const path = relative(templateDir, src); + + return !path || !ignored.ignores(path); + }, + }); + + for (const file of readdirSync(destDir)) { + if (!file.startsWith("_")) continue; + + renameSync( + resolve(destDir, file), + resolve(destDir, file.replace("_", ".")) + ); + } + + const pkgJsonPath = resolve(destDir, "package.json"); + const pkgJson = JSON.parse(readFileSync(pkgJsonPath, "utf-8")); + pkgJson.name = projectName; + writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 2)); + + log.success(`Project successfully scaffolded in ${pc.blue(destDir)}!`); + + const pkgManager = await detectPackageManager(); + + const wantsToInstallDependencies = await confirm({ + message: `Do you want to install the dependencies using ${pkgManager}?`, + initialValue: true, + }); + + if (wantsToInstallDependencies) { + log.message(`Installing the dependencies...`); + const result = spawnSync(pkgManager, ["install"], { + cwd: destDir, + stdio: "ignore", + }); + + if (result.status !== 0) { + log.error( + `Failed to install the dependencies, please install them manually.` + ); + process.exit(1); + } + + log.success(`Dependencies installed!`); + } + + log.message("Next steps:"); + log.step( + `1. Go to the project directory by running: ${pc.blue(`cd ./${projectName}`)}` + ); + log.step( + `2. Start the development server and run the app in debugger by running: ${pc.blue(await packageManagerRunCommand("dev"))}` + ); + log.step( + `3. Open your browser and go to ${pc.blue(`http://localhost:3010`)} to see your app running in the debugger` + ); + + outro("Done! Your project has been set up! 🎉"); +} diff --git a/packages/create-frames/package.json b/packages/create-frames/package.json new file mode 100644 index 000000000..4f4310671 --- /dev/null +++ b/packages/create-frames/package.json @@ -0,0 +1,22 @@ +{ + "name": "create-frames", + "version": "0.0.0", + "type": "module", + "bin": "bin.js", + "license": "MIT", + "engines": { + "node": ">=18.17.0" + }, + "engineStrict": true, + "dependencies": { + "@clack/prompts": "^0.7.0", + "detect-package-manager": "^3.0.1", + "ignore": "^5.3.1", + "picocolors": "^1.0.0", + "yargs": "^17.7.2" + }, + "devDependencies": { + "@types/yargs": "^17.0.32" + }, + "repository": "framesjs/frame.js" +} diff --git a/packages/create-frames/tsconfig.json b/packages/create-frames/tsconfig.json new file mode 100644 index 000000000..51c114d05 --- /dev/null +++ b/packages/create-frames/tsconfig.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Default", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "esModuleInterop": true, + "incremental": false, + "isolatedModules": true, + "lib": ["es2022", "DOM", "DOM.Iterable"], + "module": "ESNext", + "moduleDetection": "force", + "moduleResolution": "Bundler", + "noEmit": true, + "noUncheckedIndexedAccess": true, + "plugins": [ + { + "name": "next", + }, + ], + "jsx": "preserve", + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true, + "target": "ES2022", + "allowJs": true, + }, + "include": ["**/*.ts", "**/*.tsx", "**/*.js"], + "exclude": ["node_modules"], +} diff --git a/packages/create-frames/utils/getTemplates.js b/packages/create-frames/utils/getTemplates.js new file mode 100644 index 000000000..f0e2fc987 --- /dev/null +++ b/packages/create-frames/utils/getTemplates.js @@ -0,0 +1,10 @@ +import { dirname, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { readdirSync } from "node:fs"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +export function getTemplates() { + // make sure you build the frames.js first so templates are copied to templates directory + return readdirSync(resolve(__dirname, "../templates")); +} diff --git a/packages/create-frames/utils/packageManagerRunCommand.js b/packages/create-frames/utils/packageManagerRunCommand.js new file mode 100644 index 000000000..c540090b6 --- /dev/null +++ b/packages/create-frames/utils/packageManagerRunCommand.js @@ -0,0 +1,16 @@ +import { detect } from "detect-package-manager"; + +export async function packageManagerRunCommand(command) { + const pkgManager = await detect(); + + switch (pkgManager) { + case "bun": + return `bun run ${command}`; + case "pnpm": + return `pnpm ${command}`; + case "yarn": + return `yarn ${command}`; + default: + return `npm run ${command}`; + } +} diff --git a/templates/next-starter-with-examples/.env.sample b/templates/next-starter-with-examples/.env.sample new file mode 100644 index 000000000..9b743ad15 --- /dev/null +++ b/templates/next-starter-with-examples/.env.sample @@ -0,0 +1,17 @@ +# Example: FARCASTER_DEVELOPER_MNEMONIC="candy gibraltar foxtrot kilo barnacles foxes ..." +# (OPTIONAL) Needed for the debugger to create a real Farcaster signer. Get this by exporting your seed phrase from the Warpcast app. Don't share that seed phrase with anyone. +FARCASTER_DEVELOPER_MNEMONIC= +# (OPTIONAL) Only needed for the debugger to create a real Farcaster signer. Get this by visiting your Warpccast profile, pressing the kebab (three dots) menu and then "About" and then your fid should be there. +# Example: FARCASTER_DEVELOPER_FID=1214 +FARCASTER_DEVELOPER_FID= +# (OPTIONAL) Hub URL to use for the debugger. If not set, the debugger will use the default hub URL. +DEBUG_HUB_HTTP_URL= + +NEXT_PUBLIC_HOST="http://localhost:3000" + +# OPTIONAL EXAMPLE KEYS +# Optional, if you use this example +KV_REST_API_URL="" +KV_REST_API_TOKEN="" +# Optional +DEBUGGER_URL="" \ No newline at end of file diff --git a/templates/next-starter-with-examples/.eslintrc.js b/templates/next-starter-with-examples/.eslintrc.js new file mode 100644 index 000000000..00e4aaad1 --- /dev/null +++ b/templates/next-starter-with-examples/.eslintrc.js @@ -0,0 +1,5 @@ +/** @type {import("eslint").Linter.Config} */ +module.exports = { + root: true, + extends: ["next"], +}; diff --git a/templates/next-starter-with-examples/.gitignore b/templates/next-starter-with-examples/.gitignore new file mode 100644 index 000000000..f96c7fc29 --- /dev/null +++ b/templates/next-starter-with-examples/.gitignore @@ -0,0 +1,39 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz + +.env +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + +mocks.json diff --git a/templates/next-starter-with-examples/CHANGELOG.md b/templates/next-starter-with-examples/CHANGELOG.md new file mode 100644 index 000000000..3d9d43772 --- /dev/null +++ b/templates/next-starter-with-examples/CHANGELOG.md @@ -0,0 +1,153 @@ +# framesjs-starter + +## 0.2.2 + +### Patch Changes + +- 72e6617: feat: tx support +- Updated dependencies [72e6617] +- Updated dependencies [7ccc562] + - frames.js@0.8.0 + +## 0.2.1 + +### Patch Changes + +- Updated dependencies [01fc5fe] +- Updated dependencies [60c6e56] +- Updated dependencies [e335829] +- Updated dependencies [eee74a9] + - frames.js@0.7.0 + +## 0.2.0 + +### Minor Changes + +- 845b30c: refactor: make frame validation errors arbitraty, remove unnecessary validateFrame function + +### Patch Changes + +- Updated dependencies [845b30c] +- Updated dependencies [ce1cec6] +- Updated dependencies [845b30c] + - frames.js@0.6.0 + +## 0.1.12 + +### Patch Changes + +- 99b998f: fix: debugger build +- 108280c: feat: add mock hub state to debugger +- 1707ea4: feat: `DEBUG_HUB_HTTP_URL` env var +- Updated dependencies [18c887d] +- Updated dependencies [0ba4b88] +- Updated dependencies [f9d4356] + - frames.js@0.5.2 + +## 0.1.11 + +### Patch Changes + +- 157ec44: chore: update fallback neynar hub api url +- 548a9c3: feat: multi-page example +- 426d5eb: feat: validate frame image data uri length in debugger +- 8317894: fix: reset input state on submit, waiting state buttons styling +- Updated dependencies [157ec44] +- Updated dependencies [426d5eb] +- Updated dependencies [70a0ff6] +- Updated dependencies [d1596ac] +- Updated dependencies [62be50d] + - frames.js@0.5.1 + +## 0.1.10 + +### Patch Changes + +- Updated dependencies [40d2662] + - frames.js@0.5.0 + +## 0.1.9 + +### Patch Changes + +- d861fb9: fix: url validation and smoother navigation +- Updated dependencies [e54b9ad] +- Updated dependencies [a09c555] + - frames.js@0.4.3 + +## 0.1.8 + +### Patch Changes + +- 2150e11: chore(debugger): remove mint spec warning +- Updated dependencies [ccb8317] + - frames.js@0.4.2 + +## 0.1.7 + +### Patch Changes + +- 8112f6f: fix: use neynar hubs as fallback +- Updated dependencies [800d887] +- Updated dependencies [8112f6f] +- Updated dependencies [fd70614] +- Updated dependencies [b71f05b] +- Updated dependencies [8112f6f] + - frames.js@0.4.1 + +## 0.1.6 + +### Patch Changes + +- ccd3302: feat: JSX-based frame image rendering +- Updated dependencies [ccd3302] + - frames.js@0.4.0 + +## 0.1.5 + +### Patch Changes + +- 03d041e: feat: mint action +- Updated dependencies [03d041e] + - frames.js@0.3.0 + +## 0.1.4 + +### Patch Changes + +- 3ed2cef: fix: generate correct image data in `generateImage` example +- Updated dependencies [0d9cfaf] + - frames.js@0.2.1 + +## 0.1.3 + +### Patch Changes + +- Updated dependencies [608bac9] + - frames.js@0.2.0 + +## 0.1.2 + +### Patch Changes + +- 40d0ad7: feat: Add `getFrameMessage`, which parse frame action payloads and optionally fetches additional context from hubs. + + feat(debugger): Forward unmocked hub requests to an actual hub. + +- Updated dependencies [40d0ad7] +- Updated dependencies [57649be] +- Updated dependencies [518ada3] + - frames.js@0.1.1 + +## 0.1.1 + +### Patch Changes + +- 05af691: feat: adds an option to impersonate an FID as an alternative to creating a new onchain signer +- fb3cfaa: fix(debug): untrusted data url now uses original frame url +- 99536fb: fix: frame action message creation to not include inputText if inputText was not requested by the frame +- Updated dependencies [1a73918] +- Updated dependencies [99536fb] +- Updated dependencies [501861d] +- Updated dependencies [1598cb6] + - frames.js@0.1.0 diff --git a/templates/next-starter-with-examples/README.md b/templates/next-starter-with-examples/README.md new file mode 100644 index 000000000..72fa5b720 --- /dev/null +++ b/templates/next-starter-with-examples/README.md @@ -0,0 +1,40 @@ +# Frames.js Starter Kit with examples + +This is a boilerplate template to get started quickly with `frames.js` + +## Quickstart + +If running from the frames.js repository itself: + +- Run `yarn` from the repository root +- Run `cd templates/next-starter-with-examples` + +1. Install dependencies `yarn install` + +2. Run `yarn dev` to run the server and debugger, this will also open the debugger automatically in your browser. + +3. Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +4. Edit `app/page.tsx` + +5. Visit [http://localhost:3000/examples](http://localhost:3000/examples) to see the list of examples. + +6. (Optional) To use a real signer (costs warps), copy `.env.sample` to `.env` and fill in the env variables following the comments provided + +## Docs, Questions and Help + +- [Frames.js Documentation](https://framesjs.org) +- [Awesome frames](https://github.com/davidfurlong/awesome-frames?tab=readme-ov-file) +- Join the [/frames-dev](https://warpcast.com/~/channel/frames-devs) channel on Farcaster to ask questions + +## If you get stuck or have feedback, [Message @df please!](https://warpcast.com/df) + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! + +## Deploy + +```bash +vercel +``` + +more deployment links coming soon, PRs welcome! diff --git a/templates/next-starter-with-examples/app/debug.ts b/templates/next-starter-with-examples/app/debug.ts new file mode 100644 index 000000000..54aa6916d --- /dev/null +++ b/templates/next-starter-with-examples/app/debug.ts @@ -0,0 +1,15 @@ +const DEFAULT_DEBUGGER_URL = + process.env.DEBUGGER_URL ?? "http://localhost:3010/"; + +export const DEFAULT_DEBUGGER_HUB_URL = new URL( + "/hub", + DEFAULT_DEBUGGER_URL +).toString(); + +export function createDebugUrl(frameURL: string | URL): string { + const url = new URL("/", DEFAULT_DEBUGGER_URL); + + url.searchParams.set("url", frameURL.toString()); + + return url.toString(); +} diff --git a/templates/next-starter-with-examples/app/examples/custom-hub/frames/route.ts b/templates/next-starter-with-examples/app/examples/custom-hub/frames/route.ts new file mode 100644 index 000000000..2b10a621f --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/custom-hub/frames/route.ts @@ -0,0 +1 @@ +export { POST } from "frames.js/next/server"; diff --git a/templates/next-starter-with-examples/app/examples/custom-hub/page.tsx b/templates/next-starter-with-examples/app/examples/custom-hub/page.tsx new file mode 100644 index 000000000..02803e8de --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/custom-hub/page.tsx @@ -0,0 +1,117 @@ +import { + FrameButton, + FrameContainer, + FrameImage, + FrameInput, + FrameReducer, + NextServerPageProps, + getPreviousFrame, + useFramesReducer, + getFrameMessage, +} from "frames.js/next/server"; +import Link from "next/link"; +import { getTokenUrl } from "frames.js"; +import { createDebugUrl } from "../../debug"; +import { currentURL } from "../../utils"; + +type State = { + active: string; + total_button_presses: number; +}; + +const initialState = { active: "1", total_button_presses: 0 }; + +const reducer: FrameReducer = (state, action) => { + return { + total_button_presses: state.total_button_presses + 1, + active: action.postBody?.untrustedData.buttonIndex + ? String(action.postBody?.untrustedData.buttonIndex) + : "1", + }; +}; + +// This is a react server component only +export default async function Home({ searchParams }: NextServerPageProps) { + const url = currentURL("/examples/custom-hub"); + const previousFrame = getPreviousFrame(searchParams); + + const frameMessage = await getFrameMessage(previousFrame.postBody, { + hubHttpUrl: "https://hub.freefarcasterhub.com:3281", + fetchHubContext: true, + }); + + if (frameMessage && !frameMessage?.isValid) { + throw new Error("Invalid frame payload"); + } + + const [state, dispatch] = useFramesReducer( + reducer, + initialState, + previousFrame + ); + + // Here: do a server side side effect either sync or async (using await), such as minting an NFT if you want. + // example: load the users credentials & check they have an NFT + + console.log("info: state is:", state); + + if (frameMessage) { + const { + isValid, + buttonIndex, + inputText, + castId, + requesterFid, + casterFollowsRequester, + requesterFollowsCaster, + likedCast, + recastedCast, + requesterVerifiedAddresses, + requesterUserData, + } = frameMessage; + + console.log("info: frameMessage is:", frameMessage); + } + + // then, when done, return next frame + return ( +
+ frames.js starter kit.{" "} + + Debug + + + {/* */} + +
+ {frameMessage?.inputText ? frameMessage.inputText : "Hello world"} +
+
+ + + {state?.active === "1" ? "Active" : "Inactive"} + + + {state?.active === "2" ? "Active" : "Inactive"} + + + Mint + + + External + +
+
+ ); +} diff --git a/templates/next-starter-with-examples/app/examples/mint-button/frames/route.ts b/templates/next-starter-with-examples/app/examples/mint-button/frames/route.ts new file mode 100644 index 000000000..2b10a621f --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/mint-button/frames/route.ts @@ -0,0 +1 @@ +export { POST } from "frames.js/next/server"; diff --git a/templates/next-starter-with-examples/app/examples/mint-button/page.tsx b/templates/next-starter-with-examples/app/examples/mint-button/page.tsx new file mode 100644 index 000000000..bf712d793 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/mint-button/page.tsx @@ -0,0 +1,89 @@ +import { getTokenUrl } from "frames.js"; +import { + FrameButton, + FrameContainer, + FrameImage, + FrameReducer, + NextServerPageProps, + getPreviousFrame, + useFramesReducer, +} from "frames.js/next/server"; +import Link from "next/link"; +import { zora } from "viem/chains"; +import { currentURL } from "../../utils"; +import { createDebugUrl } from "../../debug"; + +type State = { + pageIndex: number; +}; + +const nfts: { + src: string; + tokenUrl: string; +}[] = [ + { + src: "https://ipfs.decentralized-content.com/ipfs/bafybeifs7vasy5zbmnpixt7tb6efi35kcrmpoz53d3vg5pwjz52q7fl6pq/cook.png", + tokenUrl: getTokenUrl({ + address: "0x99de131ff1223c4f47316c0bb50e42f356dafdaa", + chain: zora, + tokenId: "2", + }), + }, + { + src: "https://remote-image.decentralized-content.com/image?url=https%3A%2F%2Fipfs.decentralized-content.com%2Fipfs%2Fbafybeiegrnialwu66u3nwzkn4gik4i2x2h4ip7y3w2dlymzlpxb5lrqbom&w=1920&q=75", + tokenUrl: getTokenUrl({ + address: "0x060f3edd18c47f59bd23d063bbeb9aa4a8fec6df", + chain: zora, + tokenId: "1", + }), + }, + { + src: "https://remote-image.decentralized-content.com/image?url=https%3A%2F%2Fipfs.decentralized-content.com%2Fipfs%2Fbafybeidc6e5t3qmyckqh4fr2ewrov5asmeuv4djycopvo3ro366nd3bfpu&w=1920&q=75", + tokenUrl: getTokenUrl({ + address: "0x8f5ed2503b71e8492badd21d5aaef75d65ac0042", + chain: zora, + tokenId: "3", + }), + }, +]; +const initialState: State = { pageIndex: 0 }; + +const reducer: FrameReducer = (state, action) => { + const buttonIndex = action.postBody?.untrustedData.buttonIndex; + + return { + pageIndex: buttonIndex + ? (state.pageIndex + (buttonIndex === 2 ? 1 : -1)) % nfts.length + : state.pageIndex, + }; +}; + +// This is a react server component only +export default async function Home({ searchParams }: NextServerPageProps) { + const url = currentURL("/examples/mint-button"); + const previousFrame = getPreviousFrame(searchParams); + const [state] = useFramesReducer(reducer, initialState, previousFrame); + + // then, when done, return next frame + return ( +
+ Mint button example Debug + + + + + + Mint + + +
+ ); +} diff --git a/templates/next-starter-with-examples/app/examples/multi-page/frames/route.ts b/templates/next-starter-with-examples/app/examples/multi-page/frames/route.ts new file mode 100644 index 000000000..2b10a621f --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/multi-page/frames/route.ts @@ -0,0 +1 @@ +export { POST } from "frames.js/next/server"; diff --git a/templates/next-starter-with-examples/app/examples/multi-page/page.tsx b/templates/next-starter-with-examples/app/examples/multi-page/page.tsx new file mode 100644 index 000000000..03e133526 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/multi-page/page.tsx @@ -0,0 +1,61 @@ +import { + FrameButton, + FrameContainer, + FrameImage, + FrameReducer, + NextServerPageProps, + getPreviousFrame, + useFramesReducer, +} from "frames.js/next/server"; +import Link from "next/link"; +import { currentURL } from "../../utils"; +import { createDebugUrl } from "../../debug"; + +type State = { + pageIndex: number; +}; + +const totalPages = 5; +const initialState: State = { pageIndex: 0 }; + +const reducer: FrameReducer = (state, action) => { + const buttonIndex = action.postBody?.untrustedData.buttonIndex; + + return { + pageIndex: buttonIndex + ? (state.pageIndex + (buttonIndex === 2 ? 1 : -1)) % totalPages + : state.pageIndex, + }; +}; + +// This is a react server component only +export default async function Home({ searchParams }: NextServerPageProps) { + const url = currentURL("/examples/multi-page"); + const previousFrame = getPreviousFrame(searchParams); + const [state] = useFramesReducer(reducer, initialState, previousFrame); + const imageUrl = `https://picsum.photos/seed/frames.js-${state.pageIndex}/1146/600`; + + // then, when done, return next frame + return ( +
+ Multi-page example Debug + + +
+ Image +
+ This is slide {state.pageIndex + 1} / {totalPages} +
+
+
+ + +
+
+ ); +} diff --git a/templates/next-starter-with-examples/app/examples/multi-protocol/frames/route.ts b/templates/next-starter-with-examples/app/examples/multi-protocol/frames/route.ts new file mode 100644 index 000000000..2b10a621f --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/multi-protocol/frames/route.ts @@ -0,0 +1 @@ +export { POST } from "frames.js/next/server"; diff --git a/templates/next-starter-with-examples/app/examples/multi-protocol/page.tsx b/templates/next-starter-with-examples/app/examples/multi-protocol/page.tsx new file mode 100644 index 000000000..9668674f8 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/multi-protocol/page.tsx @@ -0,0 +1,83 @@ +import { ClientProtocolId } from "frames.js"; +import { + FrameButton, + FrameContainer, + FrameImage, + NextServerPageProps, + getFrameMessage, + getPreviousFrame, +} from "frames.js/next/server"; +import { getXmtpFrameMessage, isXmtpFrameActionPayload } from "frames.js/xmtp"; +import { currentURL } from "../../utils"; +import { DEFAULT_DEBUGGER_HUB_URL, createDebugUrl } from "../../debug"; +import Link from "next/link"; + +const acceptedProtocols: ClientProtocolId[] = [ + { + id: "xmtp", + version: "vNext", + }, + { + id: "farcaster", + version: "vNext", + }, +]; + +// This is a react server component only +export default async function Home({ searchParams }: NextServerPageProps) { + const url = currentURL("/examples/multi-protocol"); + const previousFrame = getPreviousFrame(searchParams); + + let fid: number | undefined; + let walletAddress: string | undefined; + + if ( + previousFrame.postBody && + isXmtpFrameActionPayload(previousFrame.postBody) + ) { + const frameMessage = await getXmtpFrameMessage(previousFrame.postBody); + walletAddress = frameMessage?.verifiedWalletAddress; + } else { + const frameMessage = await getFrameMessage(previousFrame.postBody, { + hubHttpUrl: DEFAULT_DEBUGGER_HUB_URL, + }); + + if (frameMessage && frameMessage?.isValid) { + fid = frameMessage?.requesterFid; + walletAddress = + frameMessage?.requesterCustodyAddress.length > 0 + ? frameMessage?.requesterCustodyAddress + : frameMessage.requesterCustodyAddress; + } + } + + return ( +
+ Multi-protocol example{" "} + + Debug + + + +
+
+ This frame gets the interactor's wallet address or FID + depending on the client protocol. +
+ {fid &&
FID: {fid}
} + {walletAddress && ( +
Wallet Address: {walletAddress}
+ )} +
+
+ Check +
+
+ ); +} diff --git a/templates/next-starter-with-examples/app/examples/page.tsx b/templates/next-starter-with-examples/app/examples/page.tsx new file mode 100644 index 000000000..63bb4ab9f --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/page.tsx @@ -0,0 +1,50 @@ +import Link from "next/link"; + +export default function ExamplesIndexPage() { + return ( +
+
    +
  • + + Basic + +
  • +
  • + + Transactions + +
  • +
  • + + Custom Hub + +
  • +
  • + + Mint button + +
  • +
  • + + Multi page + +
  • +
  • + + Multi protocol + +
  • +
  • + + Slow request + +
  • +
  • + + User data + +
  • +
+
+ ); +} diff --git a/templates/next-starter-with-examples/app/examples/slow-request/README.md b/templates/next-starter-with-examples/app/examples/slow-request/README.md new file mode 100644 index 000000000..0f563d1d5 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/slow-request/README.md @@ -0,0 +1,6 @@ +# Step 1 + +Setup a key value store +https://vercel.com/docs/storage/vercel-kv/quickstart + +or follow the steps in this PR to set it up locally using Docker: https://github.com/vercel/storage/issues/281#issuecomment-1650439329 diff --git a/templates/next-starter-with-examples/app/examples/slow-request/frames/route.ts b/templates/next-starter-with-examples/app/examples/slow-request/frames/route.ts new file mode 100644 index 000000000..2b10a621f --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/slow-request/frames/route.ts @@ -0,0 +1 @@ +export { POST } from "frames.js/next/server"; diff --git a/templates/next-starter-with-examples/app/examples/slow-request/page.tsx b/templates/next-starter-with-examples/app/examples/slow-request/page.tsx new file mode 100644 index 000000000..7f8ea62f4 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/slow-request/page.tsx @@ -0,0 +1,178 @@ +import { kv } from "@vercel/kv"; +import { + FrameButton, + FrameContainer, + FrameImage, + NextServerPageProps, + getFrameMessage, + getPreviousFrame, +} from "frames.js/next/server"; +import Link from "next/link"; +import { RandomNumberRequestStateValue } from "./slow-fetch/types"; +import { currentURL } from "../../utils"; +import { DEFAULT_DEBUGGER_HUB_URL, createDebugUrl } from "../../debug"; + +type State = {}; + +const initialState: State = {} as const; + +// This is a react server component only +export default async function Home({ searchParams }: NextServerPageProps) { + const url = currentURL("/examples/slow-request"); + const previousFrame = getPreviousFrame(searchParams); + + const frameMessage = await getFrameMessage(previousFrame.postBody, { + hubHttpUrl: DEFAULT_DEBUGGER_HUB_URL, + }); + + if (frameMessage && !frameMessage?.isValid) { + throw new Error("Invalid frame payload"); + } + + let frame: React.ReactElement; + + const intialFrame = ( + + +
+ This random number generator takes 10 seconds to respond +
+
+ Generate +
+ ); + + const checkStatusFrame = ( + + +
+ Loading... +
+
+ Check status +
+ ); + + const errorFrame = (error: string) => ( + + {error} + + Retry + + + ); + + if (frameMessage) { + const { requesterFid } = frameMessage; + + const uniqueId = `fid:${requesterFid}`; + + const existingRequest = + await kv.get(uniqueId); + + if (existingRequest) { + switch (existingRequest.status) { + case "pending": + frame = checkStatusFrame; + break; + case "success": + // if retry is true, then try to generate again and show checkStatusFrame + if (searchParams?.reset === "true") { + // reset to initial state + await kv.del(uniqueId); + + frame = intialFrame; + } else { + frame = ( + + +
+ The number is {existingRequest.data} +
+
+ + Reset + +
+ ); + } + break; + case "error": + // if retry is true, then try to generate again and show checkStatusFrame + if (searchParams?.retry === "true") { + // reset to initial state + await kv.del(uniqueId); + + frame = intialFrame; + } else { + frame = errorFrame(existingRequest.error); + } + break; + } + } else { + await kv.set( + uniqueId, + { + status: "pending", + timestamp: new Date().getTime(), + }, + // set as pending for one minute + { ex: 60 } + ); + + // start request, don't await it! Return a loading page, let this run in the background + fetch( + new URL( + "/examples/slow-request/slow-fetch", + process.env.NEXT_PUBLIC_HOST + ).toString(), + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + postBody: JSON.parse(searchParams?.postBody as string), + }), + } + ); + + frame = checkStatusFrame; + } + } else { + frame = intialFrame; + } + + // then, when done, return next frame + return ( +
+ frames.js starter kit with slow requests.{" "} + + Debug + + {frame} +
+ ); +} diff --git a/templates/next-starter-with-examples/app/examples/slow-request/slow-fetch/route.ts b/templates/next-starter-with-examples/app/examples/slow-request/slow-fetch/route.ts new file mode 100644 index 000000000..22d594015 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/slow-request/slow-fetch/route.ts @@ -0,0 +1,53 @@ +import { getFrameMessage } from "frames.js"; +import { NextRequest, NextResponse } from "next/server"; +import { kv } from "@vercel/kv"; +import { RandomNumberRequestStateValue } from "./types"; +import { DEFAULT_DEBUGGER_HUB_URL } from "../../../debug"; + +const MAXIMUM_KV_RESULT_LIFETIME_IN_SECONDS = 2 * 60; // 2 minutes + +export async function POST(req: NextRequest) { + const body = await req.json(); + + // verify independently + const frameMessage = await getFrameMessage(body.postBody, { + hubHttpUrl: DEFAULT_DEBUGGER_HUB_URL, + }); + + const uniqueId = `fid:${frameMessage.requesterFid}`; + + // Wait 10 seconds + await new Promise((resolve) => setTimeout(resolve, 10000)); + + try { + const randomNumber = Math.random(); + + await kv.set( + uniqueId, + { + data: randomNumber, + status: "success", + timestamp: new Date().getTime(), + }, + { ex: MAXIMUM_KV_RESULT_LIFETIME_IN_SECONDS } + ); + + return NextResponse.json({ + data: randomNumber, + status: "success", + timestamp: new Date().getTime(), + }); + } catch (e) { + await kv.set( + uniqueId, + { + error: String(e), + status: "error", + timestamp: new Date().getTime(), + }, + { ex: MAXIMUM_KV_RESULT_LIFETIME_IN_SECONDS } + ); + // Handle errors + return NextResponse.json({ message: e }, { status: 500 }); + } +} diff --git a/templates/next-starter-with-examples/app/examples/slow-request/slow-fetch/types.ts b/templates/next-starter-with-examples/app/examples/slow-request/slow-fetch/types.ts new file mode 100644 index 000000000..72fa08eeb --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/slow-request/slow-fetch/types.ts @@ -0,0 +1,15 @@ +export type RandomNumberRequestStateValue = + | { + error: string; + status: "error"; + timestamp: number; + } + | { + data: number; + status: "success"; + timestamp: number; + } + | { + status: "pending"; + timestamp: number; + }; diff --git a/templates/next-starter-with-examples/app/examples/transaction/frames/route.ts b/templates/next-starter-with-examples/app/examples/transaction/frames/route.ts new file mode 100644 index 000000000..2b10a621f --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/transaction/frames/route.ts @@ -0,0 +1 @@ +export { POST } from "frames.js/next/server"; diff --git a/templates/next-starter-with-examples/app/examples/transaction/page.tsx b/templates/next-starter-with-examples/app/examples/transaction/page.tsx new file mode 100644 index 000000000..6acddac89 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/transaction/page.tsx @@ -0,0 +1,54 @@ +import { + FrameButton, + FrameContainer, + FrameImage, + FrameReducer, + NextServerPageProps, + getPreviousFrame, + useFramesReducer, +} from "frames.js/next/server"; +import Link from "next/link"; +import { currentURL } from "../../utils"; +import { createDebugUrl } from "../../debug"; + +type State = { + pageIndex: number; +}; + +const initialState: State = { pageIndex: 0 }; + +const reducer: FrameReducer = (state, action) => { + return { + pageIndex: 0, + }; +}; + +// This is a react server component only +export default async function Home({ searchParams }: NextServerPageProps) { + const url = currentURL("/examples/transaction"); + const previousFrame = getPreviousFrame(searchParams); + const [state] = useFramesReducer(reducer, initialState, previousFrame); + + // then, when done, return next frame + return ( +
+ Rent farcaster storage example{" "} + Debug + + +
+ Rent farcaster storage +
+
+ + Buy a unit + +
+
+ ); +} diff --git a/templates/next-starter-with-examples/app/examples/transaction/txdata/route.ts b/templates/next-starter-with-examples/app/examples/transaction/txdata/route.ts new file mode 100644 index 000000000..b9c93f45d --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/transaction/txdata/route.ts @@ -0,0 +1,17 @@ +import { TransactionTargetResponse } from "frames.js"; +import { NextRequest, NextResponse } from "next/server"; + +export function POST( + req: NextRequest +): NextResponse { + return NextResponse.json({ + chainId: "eip155:10", + method: "eth_sendTransaction", + params: { + abi: [], // "function rent(uint256 fid, uint256 units) payable" + to: "0x00000000fcCe7f938e7aE6D3c335bD6a1a7c593D", + data: "0x783a112b0000000000000000000000000000000000000000000000000000000000000e250000000000000000000000000000000000000000000000000000000000000001", + value: "984316556204476", + }, + }); +} diff --git a/templates/next-starter-with-examples/app/examples/user-data/frames/route.ts b/templates/next-starter-with-examples/app/examples/user-data/frames/route.ts new file mode 100644 index 000000000..2b10a621f --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/user-data/frames/route.ts @@ -0,0 +1 @@ +export { POST } from "frames.js/next/server"; diff --git a/templates/next-starter-with-examples/app/examples/user-data/page.tsx b/templates/next-starter-with-examples/app/examples/user-data/page.tsx new file mode 100644 index 000000000..2c347dfcf --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/user-data/page.tsx @@ -0,0 +1,93 @@ +import { + FrameButton, + FrameContainer, + FrameImage, + FrameReducer, + NextServerPageProps, + getFrameMessage, + getPreviousFrame, + useFramesReducer, +} from "frames.js/next/server"; +import Link from "next/link"; +import { currentURL } from "../../utils"; +import { DEFAULT_DEBUGGER_HUB_URL, createDebugUrl } from "../../debug"; + +type State = { + saidGm: boolean; +}; + +const initialState: State = { saidGm: false }; + +const reducer: FrameReducer = (state, action) => { + return { + saidGm: true, + }; +}; + +// This is a react server component only +export default async function Home({ + params, + searchParams, +}: NextServerPageProps) { + const url = currentURL("/examples/user-data"); + const previousFrame = getPreviousFrame(searchParams); + + const frameMessage = await getFrameMessage(previousFrame.postBody, { + hubHttpUrl: DEFAULT_DEBUGGER_HUB_URL, + }); + + if (frameMessage && !frameMessage?.isValid) { + throw new Error("Invalid frame payload"); + } + + const [state, dispatch] = useFramesReducer( + reducer, + initialState, + previousFrame + ); + + // Here: do a server side side effect either sync or async (using await), such as minting an NFT if you want. + // example: load the users credentials & check they have an NFT + console.log("info: state is:", state); + + // then, when done, return next frame + return ( +
+ GM user data example. Debug + + + {frameMessage ? ( +
+ GM, {frameMessage.requesterUserData?.displayName}! Your FID is{" "} + {frameMessage.requesterFid} + {", "} + {frameMessage.requesterFid < 20_000 + ? "you're OG!" + : "welcome to the Farcaster!"} +
+ ) : ( +
+ Say GM +
+ )} +
+ {!state.saidGm ? Say GM : null} +
+
+ ); +} diff --git a/templates/next-starter-with-examples/app/frames/route.ts b/templates/next-starter-with-examples/app/frames/route.ts new file mode 100644 index 000000000..2b10a621f --- /dev/null +++ b/templates/next-starter-with-examples/app/frames/route.ts @@ -0,0 +1 @@ +export { POST } from "frames.js/next/server"; diff --git a/templates/next-starter-with-examples/app/globals.css b/templates/next-starter-with-examples/app/globals.css new file mode 100644 index 000000000..6a7572500 --- /dev/null +++ b/templates/next-starter-with-examples/app/globals.css @@ -0,0 +1,76 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 222.2 84% 4.9%; + + --card: 0 0% 100%; + --card-foreground: 222.2 84% 4.9%; + + --popover: 0 0% 100%; + --popover-foreground: 222.2 84% 4.9%; + + --primary: 222.2 47.4% 11.2%; + --primary-foreground: 210 40% 98%; + + --secondary: 210 40% 96.1%; + --secondary-foreground: 222.2 47.4% 11.2%; + + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 46.9%; + + --accent: 210 40% 96.1%; + --accent-foreground: 222.2 47.4% 11.2%; + + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 210 40% 98%; + + --border: 214.3 31.8% 91.4%; + --input: 214.3 31.8% 91.4%; + --ring: 222.2 84% 4.9%; + + --radius: 0.5rem; + } + + .dark { + --background: 222.2 84% 4.9%; + --foreground: 210 40% 98%; + + --card: 222.2 84% 4.9%; + --card-foreground: 210 40% 98%; + + --popover: 222.2 84% 4.9%; + --popover-foreground: 210 40% 98%; + + --primary: 210 40% 98%; + --primary-foreground: 222.2 47.4% 11.2%; + + --secondary: 217.2 32.6% 17.5%; + --secondary-foreground: 210 40% 98%; + + --muted: 217.2 32.6% 17.5%; + --muted-foreground: 215 20.2% 65.1%; + + --accent: 217.2 32.6% 17.5%; + --accent-foreground: 210 40% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 210 40% 98%; + + --border: 217.2 32.6% 17.5%; + --input: 217.2 32.6% 17.5%; + --ring: 212.7 26.8% 83.9%; + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} \ No newline at end of file diff --git a/templates/next-starter-with-examples/app/layout.tsx b/templates/next-starter-with-examples/app/layout.tsx new file mode 100644 index 000000000..e9a31acbb --- /dev/null +++ b/templates/next-starter-with-examples/app/layout.tsx @@ -0,0 +1,20 @@ +import type { Metadata } from "next"; +import "./globals.css"; + +export const metadata: Metadata = { + // without a title, warpcast won't validate your frame + title: "frames.js starter", + description: "...", +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + {children} + + ); +} diff --git a/templates/next-starter-with-examples/app/page.tsx b/templates/next-starter-with-examples/app/page.tsx new file mode 100644 index 000000000..7463eabb8 --- /dev/null +++ b/templates/next-starter-with-examples/app/page.tsx @@ -0,0 +1,114 @@ +import { + FrameButton, + FrameContainer, + FrameImage, + FrameInput, + FrameReducer, + NextServerPageProps, + getFrameMessage, + getPreviousFrame, + useFramesReducer, +} from "frames.js/next/server"; +import Link from "next/link"; +import { DEFAULT_DEBUGGER_HUB_URL, createDebugUrl } from "./debug"; +import { currentURL } from "./utils"; + +type State = { + active: string; + total_button_presses: number; +}; + +const initialState = { active: "1", total_button_presses: 0 }; + +const reducer: FrameReducer = (state, action) => { + return { + total_button_presses: state.total_button_presses + 1, + active: action.postBody?.untrustedData.buttonIndex + ? String(action.postBody?.untrustedData.buttonIndex) + : "1", + }; +}; + +// This is a react server component only +export default async function Home({ searchParams }: NextServerPageProps) { + const url = currentURL("/"); + const previousFrame = getPreviousFrame(searchParams); + + const frameMessage = await getFrameMessage(previousFrame.postBody, { + hubHttpUrl: DEFAULT_DEBUGGER_HUB_URL, + }); + + if (frameMessage && !frameMessage?.isValid) { + throw new Error("Invalid frame payload"); + } + + const [state, dispatch] = useFramesReducer( + reducer, + initialState, + previousFrame + ); + + // Here: do a server side side effect either sync or async (using await), such as minting an NFT if you want. + // example: load the users credentials & check they have an NFT + + console.log("info: state is:", state); + + // then, when done, return next frame + return ( +
+ frames.js starter kit. The Template Frame is on this page, it's in + the html meta tags (inspect source).{" "} + + Debug + + + {/* */} + +
+
+ {frameMessage?.inputText ? frameMessage.inputText : "Hello world"} +
+ {frameMessage && ( +
+
+ Requester is @{frameMessage.requesterUserData?.username}{" "} +
+
+ Requester follows caster:{" "} + {frameMessage.requesterFollowsCaster ? "true" : "false"} +
+
+ Caster follows requester:{" "} + {frameMessage.casterFollowsRequester ? "true" : "false"} +
+
+ Requester liked cast:{" "} + {frameMessage.likedCast ? "true" : "false"} +
+
+ Requester recasted cast:{" "} + {frameMessage.recastedCast ? "true" : "false"} +
+
+ )} +
+
+ + + {state?.active === "1" ? "Active" : "Inactive"} + + + {state?.active === "2" ? "Active" : "Inactive"} + + + External + +
+
+ ); +} diff --git a/templates/next-starter-with-examples/app/utils.ts b/templates/next-starter-with-examples/app/utils.ts new file mode 100644 index 000000000..8af8e17ee --- /dev/null +++ b/templates/next-starter-with-examples/app/utils.ts @@ -0,0 +1,9 @@ +import { headers } from "next/headers"; + +export function currentURL(pathname: string): URL { + const headersList = headers(); + const host = headersList.get("x-forwarded-host") || headersList.get("host"); + const protocol = headersList.get("x-forwarded-proto") || "http"; + + return new URL(pathname, `${protocol}://${host}`); +} diff --git a/templates/next-starter-with-examples/next.config.mjs b/templates/next-starter-with-examples/next.config.mjs new file mode 100644 index 000000000..8f885aef1 --- /dev/null +++ b/templates/next-starter-with-examples/next.config.mjs @@ -0,0 +1,19 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + // prevent double render on dev mode, which causes 2 frames to exist + reactStrictMode: false, + images: { + remotePatterns: [ + { + hostname: "*", + protocol: "http", + }, + { + hostname: "*", + protocol: "https", + }, + ], + }, +}; + +export default nextConfig; diff --git a/templates/next-starter-with-examples/package.json b/templates/next-starter-with-examples/package.json new file mode 100644 index 000000000..a882a3ea5 --- /dev/null +++ b/templates/next-starter-with-examples/package.json @@ -0,0 +1,42 @@ +{ + "name": "template-next-starter-with-examples", + "version": "0.2.2", + "private": true, + "scripts": { + "dev": "concurrently --kill-others \"next dev\" \"frames --url http://localhost:3000\"", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "@farcaster/core": "^0.14.3", + "@noble/ed25519": "^2.0.0", + "@vercel/kv": "^1.0.1", + "@xmtp/frames-validator": "^0.5.0", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.0", + "frames.js": "^0.9.1", + "lucide-react": "^0.331.0", + "next": "14.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "tailwindcss-animate": "^1.0.7" + }, + "engines": { + "node": ">=18.17.0" + }, + "devDependencies": { + "@frames.js/debugger": "^0.1.8", + "@types/node": "^18.17.0", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "autoprefixer": "^10.0.1", + "concurrently": "^8.2.2", + "dotenv": "^16.4.5", + "eslint": "^8.56.0", + "eslint-config-next": "14.1.0", + "postcss": "^8", + "tailwindcss": "^3.3.0", + "typescript": "^5.3.3" + } +} diff --git a/templates/next-starter-with-examples/postcss.config.js b/templates/next-starter-with-examples/postcss.config.js new file mode 100644 index 000000000..12a703d90 --- /dev/null +++ b/templates/next-starter-with-examples/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/templates/next-starter-with-examples/public/Inter-Regular.ttf b/templates/next-starter-with-examples/public/Inter-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..5e4851f0ab7e0268da6ce903306e2f871ee19821 GIT binary patch literal 310252 zcmd?S3!GI`|M>q|YoC2NGgD0$sdSmrWy(}jDwT9Em2}ZXNKG{*T}KU)WF($JGLj@o zlEf22lJqd?@(hxYOeBLOB!gtsXnyat&)H|Dcs!o(<@bO6U%#2xd#$zC^|LB_fG9A(0Ea_vqQ;+!h-}bY~)}T{xispff+YW{arV$)b{$TsUY**NYlW8YD8} zsK}5R{RcH~S?_@n!SB;vU zL3|?VRq(y5CfzV@O7$6AMK6O|4abiimELsAsGg*!k=|xJ5w(A={u;*}IIcf_a^{TR zw)EXCQel`#qc0m6S*Ydo@K9XFEV=cB{LP7Ju7>J1B&$geHYQgL4Dn zna(W2bDUdoS2(Lgxt>d%Zhf~tZZ~&0?nrke?#=G4xPNp1hI@y52ku?&J-7?p1-J{{ zg}94d^x!_^GRp3g?vuEGch}%PVuWtY)+Uvpo>-Qw=Reb;?gEO)oNoA3wj z2cq3i-A{@6%KZxWYxis7zjM)#d(8cXnBUyrM0p{P`QycV@r28HXvwSMRl%+5RmDBi zJCoGvUJb%Y9zF8T_83{OvDXB*sn;C$T<=`mwq9G@u3mTCp5BGH7kL-q_V@Zz!xi3e z+!5XgVn%vtgvWVk)tlgK1=XlYumh$%TXxNfe`^{)LBsJ`{ z(XcITZ1myR;}DPj{IDy7?SyF96Aycj#D^s*bRZgzC%iQpPAC&Dr;@Cd(fIPx%F2j_ zE0xN|vR2i)JQA;z)U-NA!&=%~(YBN&J@u>6cx2YmI+ZPz^nz%-BZ-a&CJsMw~ z@WyDkhSZSd(ePQE>vN*vno?V)MZ>i?eN2dkYfDub91YjuOwu(PPU7rRFB-0kJk_G% zdW3{rlVp^Pk%{E$Et!NT$<-W}#`lmJ#7`rot4t*|{j{9FPyge5LF^zIE0bv>I6k%A z(^D@dcRIPRrOc^0%chi-yf3-0lJUrVYW~vrQi)6BPR;vAIR;bb)iUL@T7%d@z8ZM2=NHEARaTRG}rKwCObt;-1D>qQfDCq_n#9a+W?@4kYT<;%`Cp4YZYsuf!uRD_( zO!*8_GLgm9GggLhoPj@$)G^dDop2I0oLY}bzgosg7i!A%b59|!37Ixc>ST^h-_mK} zS{dz2Y$TX=N=;*Yd9I^`u>vFY)#U6;nd|*p%F599l#)T-{=T%Pr74u1LaEZ2>BP(^ zb3D$MW!fJ~J=HJUof6ZLVlomNonPzs>T1fF76MJ09vN$x?(17q1ri#P%1CxG~L%{kiWOD z+lZ!ypdlkwWaP`HMD%QAkF1KOE;D^d6=OAl1f?aLBF9+YM$L*l?RQ!|7kN|B zYdfy^Bi7QC<5AL@xKwFF*;I5`T3^y>^_4Au2_t+loL?sY>Fu8?O=-Q|&`Aa>l(EZT z9c@Y5hRBE;3o6Z@Bm>AhmGjV8?8ew;7c^~FsK^{ilH}N^1|t;d-+1zkrq^T0Ihk<^ zwAP%Kjg^~`XdG84Mdpsk&5&OIOSJmW>phw0W|X8tcc=mfApft|^XKK`4oI)ExXDs< z3R`8Ew_CDryP>q`;s{%ht*wx6Cso@^y>nl(mZ_^K{%4Z0Qg1T1hoGhqUxaI{hsAJtfP_ z#C32|OE!5s7@NF5$LqzI{}l$8?E5SE;x6TXk&3np;uH= z7#=3+@ku3xaXBSDZ6r=Ytc&iyxjv4p4ri|+`K7WlI1gxRug3zAfjd%+m7Vw$e9TQzn_bP66ZlS82tb#(zY~+W##7 zzpX#NY<+Pll2aCEH|75$O7j1+{C`@1k+ZvG1N9X->%`Q{ag_R$Gi)$^$zeYn#Ql*U z^kE(Ow*tqU|8v}Fk+3-~OZ-a72}sC9Cv&6eb8nhXRAnhvG?372xE7> z&`*w&3&#I5ve2VX$zmr9GB}2~@sW79ugq{~$qYX&i}QdF_8cjb6Y(Q?^-@_4`Fd$d zj=@UgoV%3sa)iYZ-%mI3v!d~b@eRbC+=ah3Qiop`^_A>{g{7GIk{r9O@9(pAmG}_1 zG>XZ;kMw-I81_Z|;*#b5v5AY29F?`0{EMt%C9ms3$qy}+&eqnF<<<-%r%yWjbtb%u zd^2DsEc34w@=J|9y+Ut}KrDRQ`%)aW!I=(rzzF2&jHvVng zKGweg%GpO{jZdL0w-3v5>^5>7#Fz0o7p!4i4mpFl4$9y>&$Sn_X1Ik?O#BA!i*h`! zm;LLwqm0-1k~}Z3BrlxIbw?rBeA$o*D~a0;1hq+eUrxJV$jZfSm$&RB; zTps->lx(h9iuGkuDd5*zhJ@Ea(emINq@{fb`-}&5A{n>i@Kaqxfv-Dxv zr4N@>iTZQ#b0LSgg^*1+5q~Qbz$Q2ft04o%!!Y9`kLm9^Y$Dz1#eHaulDXJ)4)H7P zR7w7yklWPZnQ>f;t+VENhh^daCeA$O{4DyA!nkrCvlES9l7$_&3RjaE20Mc_f^(;f zJoX{hI&*H!gf!wdFjr>D0G-+q0HsNZNZ-t#xCvDa=#3f5sn0%}$In0Og$el@D`Em7$E0h$*VxdbLJO%D$ z=83aX(#(CBe@*H!M$93e;wK|>w!22gyWAsC&d8pf(2IFjB=g)nf3A06j;}TAkaJiT z^DMWszmFr##VDpsIp#q)9hsTi*!`{q=DqRR1KJeqiJAKkyC!SfYT0e@*N;S5>8zz+ zIWinwufwLYojm!wA0~fjANkEZH~9w03RuZ~WuBX))<7cR0w9icC5bwd~{>CX9XM`DC$=nj{i05u8+&7G*X5=Um(7`Pa9pD(m$8 zf0kFLO13u7VKaR4LS`R{I7l&&o~$Ryyilgh!v^NDr!cSVv0g4)LmgzRRYf*gp6m*P z1120JlD0N>?8&+^;Z0T{WdXbLaXTx{C8yAqV?zQYmBE~I4#Jnj{l{fYd!eEdbFSQF zY}#gA?JQYp;JlI(mndHuOxRf~8O{REt;-qvMCP!W$Dd1<&5KkaQ%|8RRRuBw{mtbX zVKEf(Zb?pD2Y)&`coATz`DMbc{7Mkle-yaqlAcJ|Yr*mi?*HoD@ z*VL&Fl;npJ3GbusxiZ(Z5gJc^6P_!>w6VJ)%59alp-IH0NGqp`vxabaDW?{7ZSsx7;UPHfXNpq4WQZvT>=bAEQ|}H{fT; z__)_4(@B-#;at|;&cqc;W?YesXMH~$pCyOO9mUU;!SSnMC15M$8Entcsm6}%8ES(r zlmaJ9Wf`#HUD*6?YS`d!Q(nFzHl%b|f<<60^#wXvakZVX-psGT7!hfmm)9VVa zRjJ{%x_*2$nP*`A$&O1@-X9!y4%R1=eme0vl6?xfaul058sAxV#mG_;Z|GcxkQ(ge zs+0)G5KW^$ode3H$&qqtl;Qe2oFyCL_Mn3Z)dD}9q^iXykq4ZW5i0bOBuHnhL(nUF zY~uc3Al>x+{{_tb8Eetn;9jmg_ipZ?l1C}{xf^^5tf^K zNaDA0oxIg6;5iq0%{?4(ePAx<>op0tO6xd|$5Ah3K=9$kvsac-#F4wsR@-HWSG1v7)w3$r5<|Y&>kN8&9z0$un zW&I59b*+4}>YT{JzS~-bx-SRASnpE&dvtSOUW{DyIoe)dKc02T+y}d?KQsaTywDg($uOq-$z;Z&3R)3b+ZKXJhD(Fa=aCIU%og2pVhdyFZJh= zKa1nO(2F&Bjq>|aJf5^2q@^KG0eO+@1Z|sh$B8PXzJCr$AYUHwsPKd^{so-Z%zn*s zZ=NrIP10wX`xNRl_nXdPkY48jAvO`PWn zbq90IURMtHbBk?rZ%6(pD}yk3mV-G@E;n%qmuku~#vXCG^a+_y4x|3I^gZABPL6-y zl5c#{Cz*RJ@}?n6A+jzvzPV4NKBMOx%55cIPrI6!aa~N_zUVK9IP_k;$v~cD>NaU< z&QbH8MKNP(@O9}$!Y7POGl)BktsbCEceD3~{#H9_lE(P8B5oye<@it+`d#ehAuoMH zwhYp9VKH)<(%_>5CYq19Pt)4xe&p$xh$&Pq&{USXbFnR)JJFh^*QXYT$SBEHD9U#>IP zLBmK(bToME>`XWXAqX0Vx?q%Vba zzu4?i(C2*aEA!EPEA*R0o0(wdNgk{tyx1HYXnU@)W%hRS45ZJaOlRVaTrr3@*NBGn zNdHbC+79U-lD2(XnL=t`$iD|^GrW{vrC(xT&w|w5i zH}oZbWrX5|_y$w=V#tn!kMD|{6aOu||8 zWtf5RA=ZF=($*2q@K~#1vE$F(<6A|3DS%?LR=bon`zmG)H|vG5KiZf;G1+4mqmIe{%SDwn)vaM4TqorYJ!Ph8wnrZfxi+=JEs0rs7Bb-Umuw-$8O9y zBGofGh^(!%@ModFh3GHaoU_b+rjx<5ro-$Fn6-wm*`vdz%(-Ki@zI%CQ_Xs2?9Sld zgHXR&M`p36m~&uZlpXkH4foSbeH@#zi>b@lF{qRXejBF#<=itYWgZQ-N#i&j88?`D zg}j^WMAnEzY#~u5=>*o)MF0L=bRz2{$IOFSrhfXAPJT1*W>9tjV}j0$rl5=6gp0Y) z+F+i=(Py(JX8F(0qVttC*v#Qf%A2+HDCN!m{Yv(%^N~3{GQKDJCZId=pkK3In7`v` zz9+@`v{Mkl%n|eV`!woYj&2HAtI`ZEYok@DYSM=s>NVF@#nc@#`-HT+3t848cb;j} z8^F0cgLMQ!9mGI~WL8!!7V2JO^*U zXYea`bQPg7bb-s@8n^=O@LaeE3ZRHP z#Y9L3M&R8bO3Z-2c6fM3rk@g z>;UrCIV^lc2dY2{bcf-P3G-kjY=YfD-n!(iTN7FVdFzt5E;_A?PV1u6y7^EjQqO}V zXbS^iJY>OQSPOYj07W8aCqgoGhGCEa*{~coz%Do>W_gnO)gTpm0eS0_w?6h?|84jZ zeimuK7&O3^8emHeu%!mrQUh$M!OKu2(l8N50ci~x+lH&)RoDYZL>i&HM(C~)^SIGu zxD6hL{eW(hNlzv{ne^m-Fao9kZ6wo1^1JZ0NMi*URO1%V8)&of4e*gjleTa*+yW26 zbMOXGuF0<==Y*jyp#K!?Bn2C2S_!a|rvHRb;TMr+6`&Dxf=fl3SA}NK6OgO3gKIj|aXAs>qP z{4wKr-U5-fF3b{XR|{Ih#V{6FuiM=ZPs29&1h9|xXFvlW?tIpO^RI_{;0a)kozEOQ z|9g=R)Z3vBTn6;D1MPOe4lls=FIWca0XwYbMeq!4hy8F&q;q*_2pwT4tOdrtGh^R{vF|brG9Vj}vC9V71<2Vo z6?(x4xDMvSGI&R%TNOwF=5V)lfX=%efMSvEq;)5)J89i-h5G;z4tWdc!w~u~v@#Gkv>S|p=|I~-PZIp0G-o)L`0h~pw78HbUK!^p01IZT5) zVFhf2_uw0Dxir*(me2<#z#Lct*h5+#U^8jh%%}vQ%~2iT5*Q6L;U|&N&0q#>g?(^T zWDNPoJS&oZ8$1jz!rSmA{Kj`6FyF^Eg&x3ojb)yXQ-Ch7a^N|U@z}z6^fbOuk^#9gkShbZGG2z=fE`?e9bAJxu9*P^BGaw_>}1+qfNf19?=;$;M!VB#cY0kQ z&-BOPAHW)rIUF)!9x&FKjCCeso%y54wQ*1nS_1W5haA^EFLFKozrGiw0c~Hu1@?-} zxCGF}4L87HC>EJn1yZ0pTn^LVPN1!sv^DcRksG_f_rk3op!b`w{hQF?O~l`H8C(N* z05aS}pJtDN8{t0qJJ9~@j{&>7IUdf2^I;H7gj?Yucma^_=Fi|4ku3C=)f}*=tSjMK zV7#)>PZqY9^)`G7*xoJJ-Yw|*7V_Rg-do6f3+>IZpfb?r9NL^in{#%F+={Kw#U|%6 zu5;S}<2rYn$ZhECcJki-j>z9Cz-{m_6o_P_zw8A-`8$$;a(DCv>biq@a|da6JO!@< z`R~9+?raBZAy4G4>Og<)LdLtUfa!oO-1Qi|0(${ln1}3lHv;DV-N!}dCqgoGgrP76 zZii*C9`?XNk$ckN3y~b`I%kW>y%zxEaxeN>uwCRn`g7knm<@~I88Gqt;h4z6^3V{b z0pq-o`tN7V@5i?9e;(+={q*a8`n3p|79rE3&OrL244}-S<*)&E!6A_c1gb$Q^nx^) z0XeW5av>j%n5`J739SH~E@rG3qnpL(=0OcLU<}*{_W`!`ApLysWB5sANgL<~=wV4F zd?)fyN7yN{v=h*urR!h^pxdR`|HDIW=X+Zv$>H;!u zU_3XxF7k4JxC+qk%k=%_XW^glDf}X`u>v%LPB0S4xA75p4L*eukyq+KC%6=*!aeW= zP|qvmd4)Wio&;?1A9F=stqrvQD#x#)yVvM{E^_4_5!sBLZYF&*>6;n9&EsG;EE0LW z5?l$_!rkyV`~yCK??krPPzzea#V`@>0A$&M-nV=qvQ+`{ZoL4mfNKDGw~}WodA70U zY-7x}Jp|anHpXS!XYi}YcE)XcW9R~x0cE#S|Mo}WWq2397WpS_{IfbxZ(e&q-)|&9 zedqv#;XRQz>C2n+;VtBT>nvyiy{4DYz zcK;!E{~>nr;pcE%Bp-XoCoZ4<@0|>{!Fs^1KSB>5p@)y21#Io(vtbf!5!r`M_hI+@ z-r(DkdIGxMPrLiqihPP5KTQYZFX#fFiG0==UKaVhAxszfg1Wv~3dckaWCHbn*&QAe zIf#88q@IIciX2jq0eK={HwXIsH8%gvQ}C|KTLAU`+!A)f36W#;;g_r7JN8tOxd zz0H0nw*2c3*ayt5U#a_ec|f1Xn?XnD2P0q#%!VAmE{@ao@m$!&p7jI37@qi^{ZGmj zqswCCDn_2)(Bp6D=ww?!o)UCkG8(Y2l2?H5c#+D$xAG{y)rV)hif?yOIs@ha-`t~D z!3KC!l*M=ESf7guDX0m2Gfrp>nD0Bf8=ip8@G*QV%BD_x7A%72;1^L2-%R6N2Gij- zcmVi5Acya~aoz^L*T(rll*{*^xO~Hu+Xx0h7UTfmljCjy+VDv8+QCII9?0V@hdej{ z#iIB$jtaMjOTc^w4&SiD_uTNUHlpG>1K)@f_ZXZI6(0|0!8vd~Tnr;&Dm)7B0^d25 zK>riY1=>tNKMAx|E&;m1M4(^gUKCZnGV})eQvn$(pr;DY!&X3s3VioeVj|FoMEaOG z7tk+znyR7$)u0QYuZoOE#f|W@s7gIyn5fEUi>gvx)EO1vbx~E5;2lwCrUHGc))1Z+ zRlOoGmerA?27RkRe`>q{MWW84KQ*CNHc++}V^q68+$X9I`mMwF7$t>ZI_wfvw-fvw zeiT(N3${UtsIv#dLx6tk*M+h0hNuQ@;VJk=R72t#Qnumuq8edKjjn_xK%bK0&7Gyp?^(Q0QPqd-}ZG5ZKWVX3T>y*$CT|reNDqazngXiWNG>wY=IBpEBIAZ zvv{Zl%>lhO8wAMI?0WbZz60uSj=q}DgJtj;{3I&XhBKitU>m8}M(Rko25yD>;R$#d z-hxj6xmqZoZ!H?YdC(iKfH{C{Esl$7*%#>Fxh_nHpGCDg3pR;rO@CU`PHWm}O*^e= zr#0=grk&Qb)0%c#(@q=OX+t}0Xr~SBw4t3gw9{rX+zhK=gQ)XJJCC&U7^m}?C+8K4 zYOA3NTmYBCY@q(O$k7g&+Es^hfb@3#VH6-|yW8LacoN=#uSK;FLu2R-Gv58J`&;-}MN}6D2Es&G3fM;%@^x(i zx5Epfx>W?)?shL=``umx#{HQWHm-&rz;YH zI<7b>YB)L>J`z}yuDl-5$%p~41_+O=4_CobpzbvKk=7Be1^StGK-8!vKwG1bd(?fR zMkCv3;z;=$DYz_LK~p{baa_M7mzufxtIPP zU{hlqNCIqVEcQ5d3S`3yKp$iGK%uB{ae(aOkagTJmx2Q56RFKhQoD` z15d$L*bhab##e$A=m}|nO^ja%&p;l04#lFbt_rEp2hw3SEQaS{2OJbNL7)b-f_^X_ z=D<=|54+$SQ4>Q@8`{DpFbQsl<**TU!x2%FJg5g9U?^n3ov;#Kg?#u?)Z_$c2%X__ z$b|W@8eWHea7@&cL}&utVFb*81+WITi<(*!kbP=jppR2$!8~|RR0icT-hj_UU2`)$ z08hY6qNZWr(|Q0hP1_@C`T$@aWyV7nxJ=ZwVYp7zbuFO}j0XC0-3s_X)b+DP%}9a! zMcsgn&!oMXF9U7fh~3{f2k6JFX@LFS#5!=(5_lfo6#si$XVd@Lv^^WW&wg9f%{_sB z-n>dwR!2B0>XzO>y|*xjZ~0o(90k>33_J$R>p4G*x|R8GEAh8BhIT-?TQ7sF;Rd)D zo`lV!=GK7=fpM9;SJZ9gAqj>6>%r~SAQe6m^|xn5WnTqZut3xu7XdoHV~40alY#!- zi5zz^R(I8dVXy`YM9r%V^kZH&F#qSB6m>WG?qN;2Tl* zoB`b+18DD_4SfX9A4(bZD8*UvHc zpF=0lJplCe`F4PAo~JL*qmviTgOM;57QhzxSkyWPUKaHt`goD?S&uC1X8?7qe+9k; z^z~8&zd^kWlay9ry`^c|qPe<1Ha8Ugd>Rr<<4 zj(V*dFs`rVips46Pl(z~|2H$no4*qEdJni19s%_5Iy&8geQoIgV`09it#Pmh-Vn7d z6Bv_i9B8S4tjfM1fbV<7=w4-hEGN9Y7V^tTio>^yb526dbb8( zQ}51#=V1r@Eb2Y_$exIL|9U__yO|?C9r4k{?ybO>??z`IXs7}WVYH|{*wr5FY7cg` z2Yu{W4IAN@s1I)d#xeg)mIG@Br);wGVmsT?5$4 zC-h~%z#u?>pUx9i5QeLOx(d*D!2wa9ode4NU4DixKO^q*MxwsBOw<7z&H(1~0mkLP z6+rt3u(1P=iTbiCTnitFI!NCR-UI0ApgI0U)K|#!74m&`BQU04F$RZHfH63<3ef%6 z=fdNnzNrk1*SDoTTGxiZ!6Q&C+8PEo!ZO$l2SkSwp#uzuDR5M@ zT^^>wKSVn=3OOW{AYd(zlp9^0nkmgkKh~8)iqoMV}QD<|17%3WS|c<)&p{%ML%lN z$C_6{9u&Z_2({2vE#|0*`F30j3A*>}J6MiQ8kIRk%FAJ~x^)?xBr7iN-#1ByU()~L zB)*+i_%8S)N+`z6l91Tqh%26i`BvI^Nsw}stRRU}QL4xpljoOKOp4y1pR;|KqrxuL4u0^VvjoU&^NS}1|RVqDw z%GAkf#JFjr#;DGG+y5lh-gjI1ZnG)ZPM)Tcr%p?sqLMN=P&K9_iK;UF>M7$?`RUVB zTc{9jOF52vt`y?7l7rK)9X(wNreB*eT|UaBlFa_UPsaHY-yQ6`Ll|u( z?5!%x4-F@z{m>PJ_;44gmzzR31>ADHa##hM zsfN9nZ%9s(dc0iLP?DvIpQows4)9xHZ`izd8v8RXk0;L58T^^JtB6YoBJfSzIO5_@ ziyKQ^+-Y&?#IY9~`!i+75a-2WBK5I1%(q#W{+WEEh;vG#{C3lbvrmf~Nt|ziv3O>y zKd;QJGINRy(hN5w%_UXNl~#ncA3L%Cgo~cVPx6NyPXX`1g2e+Kx;$Vwi zEjI9fU5lYD+BC1y+-bI}*)z@NKst1Xdd;3`dJ^(sE!+;5L#345lw~P7DeccWd`^ez z$E(k+KB0QAGoMN5kPsI??9~6bBY*I}DekFL{?p=Whj)da@g}+3-E4Q9+udnvAGBMA zs#-^^;Z}RAnm(xy=vCGcy+F6pl{oDzl6?AW`fPshVYr-QAGLqBkJ-Q2MfR`uar=Z_ zZ2xATv`ZXul%pNX2|2doIIiP4VJFUscM_a(PI;#S-{@b_spM34syJsjRh=`PYEE^h zhI5uv+o|c)qW*JKk?y2>>PvJwzou}fUZ|hYTl8D{eO;)3v0UqXs|&xHFos`CxYb%| zt+t-yR}$W~%i9(B^?*utWxI-9)jrd%W>>e*w>#Ju*q!VJ_ClNUXH5E@lBAP#U0qL~ zt?TOsx}k2QlXYX=M4zKmbW`0-H`l3}wLzat?_29O`aIoMx6|$Q`MQI?KzGzh=)gkG zDhzp5eWui6(XY-*6|`YyTpW3n+%1dzb_30omyli4PH~&LSCbk-;96%S`dfWif2WU_o}zo| z()l`HLi!{98E2QWHJW)9Lf?(ubKG&Kq~-@Q8eFf``^^lzwWg)oqjuIb?ECL$=5-BUk44W zX=t%&sYI%ol(U9fms-QD%dE?-E0{@FS|hBHR+=@+8cl5x8?cPe8l7Un>>*KJ>k^Y|r*o$gXYI zRyMy+@qu!@YF>5ac^7*Zt2px;5GvlA?oC(aylgL9mFHI;o=_FMwcc7)+55=*SXBwv z4>wd*!%f0XRP}JXa646l-)NYl&I;cazD?B%zZT9_wZq%P+f|bJ{RLH*K5J(2g(Cd+ z$q=qsO2>5q--i6ZIIeaLyNR3PUWEj4e`S1GS;|W@JIPLx=59T=9^V3TrF$jc8(k`K zLrG*#*Ft}F>=e7H-OO&z{BG{1x-HzR-3jhQcM`cHt5a3x$=P;&yCJis0XCn^oJn&> zxns)A94*V`VqUpfEDy>Oo@OqUhh>>OBFq1qtJc4qvDPeMv$E0*WJ%u#xkAnJDcRn@tFV1$So$vnI8PA*r%{j0NXTLu> zBbH4M&W?d!%c&JPQ^wAhffkk_@~{RWfC@2&!1Bbu%JeEG8WXtj#+E$ zDxkaF!|rKcXb-eUM6L+zN9;%K6{X|spOu2u!JN^`+eys$E6e1lFBMn`e&1e-eXBj! zzRkX!ycPcNTBN3Zqdm*M*`9M+ZGUv#Qks`@FYPtv^HM2xip0^%?Ob`5&W$#NQ@9$h zhU`Y-_S|8!3qYtHA+ttB;@ZaITKl0E_PKUz+r&n#$J$E%$LwcHW4PY;>_BI|?B3B- zFQ(5fc2|3m{d8#ww;AhX*%E!w^hi6+9%YZV$JpuiSbLm(l|A0hvLCXS+7H{y7=h(x z45)jh{kXl#e!_Xp$#ph6uRB|utOo!=fPJy&q-Zpz4Nk^ zU89UPAHxETMn<85h^{^BIj&I$n!2dNXwzIJbc*i~pA_%J9gcg?8}9Y;T6#5{{pjQw zXNfb{$#h0L{hSU?GV}ONdxQOyy~NHArG#pP9IKGu1bfq3XDzknSW~zT>1;K$;`C9y zPrt5L>1^GVYu!Xuq&`<~s98L^?~Hp=ZSP7jAwIBT>S2Z7m@uE?uC!%*KG5RVvLfL+j+zi_d_L~t z*O5k;vqysQ`Iro@Vnj_n)9h&pJvpX#v9JiggGGx&6R5}Z&K?>Ki}dsBOC+A&F=8DO zOjtNeo7(Ez_4yVXzjx7)a0WAV#l`O@-t;aK61m9K#Lku9yU>q*NTiRchu=)w7r&Mi zdguEhy-h8lt?`SAMJnGH@qaNX-mE0_&i5m|)4l~!f_rpQyq-vCr0hkEVz%@q%vG&@ zvE2{5zS^FRTyt2Fs@YH4PfB%r4fa>Vncz&|F5kaOwbI1p>ec@b^$qn^8~pk%jHY%K z$LebSL(M|X)Dl0fXEd#$*w|jfP^C~MHQP_=5lu;ukd?si)fK69Ki>Sl6mn{Q*U2id z3RGV|wp%oIzc_k-& z=Sk;Sv$!WRv7Mr^Gr1NWhxMB{^9x!=nsL-UF7hw0`YFctO$yg0y07_{h-DhfH}U*Z z8F!1VWS*bf*u9CZ%|2;uiCCqvcoP>#j?sQDW9t_8T?b?U*EB^Y6^yNGy^|TD)aTJS zW9Ld560G}vj?s~K}MzU+ju>&Hh~x%2eoQTb37%3gZ>mI|xC$;bS< z;kW8?^_}`fZL+#s-PJ#>H>|f*p0zhrU%eGNV#n({Tia*Y?ezuNO&>kR?q~PY z6Ii{*>xryhS^7HG@F(>3_N(@*dM>}fH%8y)JnB5EA7BOFp%**vIPd9I&WFxk{gm^m z^Ob(u`NsKPuXlcMe$|`Y+3r1hoB2gO{UN`o_n^)fZ@=Y*>xAoA;c(q> zT`Ml!DBQ@34>t}swi3ck!%eMn;nZ+Tt31Ca*Vd{SZXa%MRStIucd)9MUzM}Y2;UUG z$*LN@IefFlZ|eD4PQy==G<}exNDTYK(ogS>9d~3rxB5r?Hk_pD^^8&~$0k4XP#YVm z9XF2-e2bjrTjb5YMP~aJIp4R) z2Yics(znQ`e2ZM`TjX=TMZVx$#v=8X#v=7WW0CqRW0Crhu}J+j8g}&T z=>HTMjNMH^e`XAVm1-zwVWrKunAngWz<+16X5gAXv(|LbDQ4dR*ZgU@EVlDdhh3~r zdbBiR-|beph`qNpGEqOHUy%Fsi+Up;-PojGl}B{0-XbgXHgF?Q#*us5Y4^_>& z(7H%fw=TAZsM_p-T&fze3v!uC=6ZgbYRqok?W!HWYMRHlZ@z8itGn5|_)a~@p5bqL zw6n@trN_8A?!7wQz0bW*k8_u}OY~LlQukp!-d*WFt|z#BL$ID?emzr9cK5h@^b|MW z&DT@ikKK=ThWXu0eT`e%23(GxYWBX4KL%_Z1H6IyLGM!UQvHy3xp%o<>W%fr>W96nysPvw_CTiSN6a3G zUg_QF-KZZozkR7!dAE4C=qJpsh+geI>OHET^d9q`&`+7Y5&bN`fcc_c>%HW?te^AV z@^I6}=;Te)xR-cKCwu1$t-rhVV@NPIy*$mVP%pJ3L#z7tRX* zO}`($BYX#z$FF2!dHhNymd6eZmd8Jq$8Ta{d0&PP>d(zDW9kFpZ^GYWfBZ70{+8M4 zl)cjT=cvXmgmr$rp2JnbL}#2c*}29U?@V_$Ig{O2-Cx|7++RKA{@{hYi{0a1|L~8V zIlF7Q-9O)%^OHHh`B!4Lf5phPN#qVcaxD-^iR=e8i>CA`Q)Upg`T6w%{M1;AW}VC; z&D5Vtdo|7VPqZb?^;!>(yy$gy-N~)6xS)9>cCTppD`-n|LV};t3ydmh5N$^-bp58m<`^%Y3e@XL2PtPDc3k z_vA{W4Xa~ArRA9O7FUsv&_cw&$Jyc^KN9s9`0)#(=?m;g`T{$WzQA7K?BL$y5x<5Y zbWb$Sl#0ZeawbH%Xq*WJaX~(6LwcLOCvjI1uS4;X)-nR_R>e$M+5I$xfjTyj| zcf=-JL}RM4w-tG=qf9;a2#%EfP&74(Ct&R4QHFCGS4qwN(u(#>uKA_%RBR|-`DNvk z$|se}E0<9&BR-d3G?n<}@r&Z;#m|YK5kDn9J^u3e0r5S#*J~M{9A7)WN_mj2`o?vQYa7=ru6|sNxWqUoTpa$9 z`MW>7JN#xiH@rT)CcGlNI6OZ*H#{?(5gr#F9=;^pE8LOa(rv=}QZ<|q)?Sf!#5=&w z?JjS-x5<0nTkS3L7J7GjS>AQtByY4g%g_`i&*HuFaAmPY8@;SSk@9|6Cuj`HadHs}Lp_lNK>`pyL&(zcO1U*_` z&a%u@{*lrABcu68`jS}eM?~_oFX5LP8O=W^ntxC<|Db68 zLDBq!qWRgo@XL*g<{uT!KPsAkR5bsnX#P>r{6nJoheY!aiRK>?%|9fXe+c|*LtkGT&7nC&`4B~>a zMvIX+qsJf=lr_2x;)1e9pOHAD(I6C*HChegg0e=lL0nMQXg3mP^c#eNvPQ>2Tu?U9 zv)Lbwlr^D9SrdwsHK9mZ6N;2Ip-8*vHdZ#!vxy7J26{GeLD@jhxiw#nPvc_tIxS(vHXJm?%4fJf{g0g|0O!Y6#06yoJ(CtI8|c}@1!V(!HgQ4Oz@E*%XT+{dDClpXXA>9nH_)?*3;G-A z8A)Pg13jC#plqOL6Bj9q#L;$5DAKM8MPxRiNLdq#$ZSGE*+9?qHdZ#!vxy7J26{Ge zLD@jh=qFY-(6fmP%F<8YUQAq278#;(fu7NAOy)q(CN3x&=$V*U*+9=GF6eKdXA>8c z4fISMv9f`lOGge^lajSvVopWTu?U9GyRE`4fJf{g0g|0OZ`h{wyK$`&(o4b zdT5Qd=W?JKT>*f-xm(|f~#kG49Pa3p7!Vdc`y`BB5=Xolyj5o^e)Ys`r zdYJCVHF_$~#A@nF+EXWaHT!_tr*^2VYMol6>QQeWo}s014^Z9;as6M&`%(M2`p?tr zxbk15=jj=G3j1Z3v(wg-y*1t>8wOTDx3)#=lQrA)QXf;grQ{CCYXr)rH(weFYAMFldr!!=l!@JPjuRnu(53SGE zyb-I@^iZB-bmiT)X1oViLnmrS6{{cBA+=xa<_Tf0T8|c1@SJcy($7>GY8>)k!V|-e zw9!N*sj9S~c^~bF9FUJ>mu%-*$$EK4R`I^dBKACP=g!@xBxGucgiIYK#7Ycetlsex3ilhLxQld(`xpSd=QNMNpSf>0opx%P;} znfVrJ*MuVNnk$4LHIT~8!5}rL&&<4_Y#^06+eXTovuF?s>N97!ATFrIoP8p3<_r>q z0;$ZbjkIf4{2(=u%FN#&HK@eZGwJEy&KK6@k=I31l%PG_f!)0I7w z3!NTLH>W!_R^;v2U;gloli$~>*qV|BEc>ro`uWa2Engy^uXwfepSRRaZFNu0#e2LCyT8Hz0Y6Wj z)ADR*zcn-ZpX=wSby|*<>?~g5|1a~?&pIuAF1l;U|7<@My+=ndvLnvtVHo8!KaJ1J zpwo5^PwJdr&Ok<_bhO(`9C5v!KF&o>U*}@pGU?9_U1TrS%*jY?)hNLeBw9EFS2<>s ztly7(tX`$-$-bCGT36vbR*1!EYDknb)az;`*IAP|ue4Q3yu17(x$|TlyXHBP#g6%C zuAzFdcbj5bi~aKz#(p2M9>1oDZ=^DR%D1IRim@saDoqRdF_F~LaA~@EyE*c2WGs7B zn#YOdiPUrIacMq2yH)1j)OUJJXk6D~(V;n_hN&=ztsj~}j^bD4fatH6vJ}TRI zBcr^krp{L9sLou&-NfC-UFt#gxZ0-j)H~_}_1zz?>}B76Y{7ec7jY(@Z{HI+hwu*2 z1Dv6rb~ZY%IBz>UOZ8@Nl=l90>vI3fb)F~F?vxL#I=r9`MO~+`6Hyxv)wz1H8u@G;=L{nSGLakz< zb7P^Fu@LVgL`(1_F&b(f3pI;{n#MvYvCuiOP?K1Q^)XsYaxBy+7HSv^HHd}k$3kbv zLiJ*yy0K7FEW{@lqiyiMQ8ZL57OEKw@d?IgYK>T^dMs2e7UC=s&BqhaXy}Yss7fqU zITorE3ssDT5@R7gAsMZud@NKh7D|YP;$tD^aI{3&55-moYXw#mSsl1aB#-&zR^;r2 z;ab`L`!)U=NLs8EZ!Y|QXZtrHr&;ww?*C!#EuifvvcB)rc3KDo_gvftJEyy2c#?Y# z?(UEfAV`9Rga||l;UdA^-QC^Y2ZzCBaMuC8->$v;l9^}beV=DN-&)_7tbhHx`gE7> zs@hexyDndv+SMW5SEIYH#&%y}k!H`0>b^R-`)XwO)j{1?e6M0}9MFBWfA`gX-B%;J zuZDMD?c05|PxsZ{-B){cUk&TN+OzwL??cRFbSL=3PtNG_)oE9&{C_)gIE`J~+#r{t ze`<5+mSWT9G$5B}M#w)~-t5cP*6g`j&%EcNJ?pc*G27*{zCY`0vz|Na@E)J^c)Q2V zJ*M>7tH+|V^qXa+S;Fia_PYmX%ck3571fb^#{TpX$yRQEd6&2yFO0obqrNoz!`DZr zMt!0s!(Z6%y*S*#?b~j}ey#7{>L1L?&5_<{Rw!1$qVrs5cR|aOZ`SKmNEa3a!7p5o z4}QiSO{!NwSCD;uauK}D7w3b67v$OCCETvyMcj$OUvVb|&*P59u97u9G}3|SqJXmcoKJ7a3}7#;6B_50agq3F~ME9Q-XVOyMkMA#|L-dPLyxF z30YHjJ=ar$8{}7X#gek`wyOxPG zCAeMmlP;ZTBt7Uu<^FlN6M}Pb#{?J1Gr>8yqp|zAlU1B+YnNl;dNy;Hhy-+yj}ZN++6$*h6pM;@HUdozNmxRZl3D8oC0W4N9g%)p%%oXMRXgQK_} z7o3edA()OkCO8%M=-@2eu7J8B2gmc|Y{5ymJ1t?)0DwcVciH z?xf&o+(Uy?a1RTP#XTfA5_dG?!#~wcZO&i<;S3HA<<}{}VYpqvB;4@GYpYQfr*tk2zByPdh!)%-2A^J{0aMmK}?>M6QPhn45<%o5$2btT`y z{G|21U}4<5gOqS42Mck1XD}Dn(}G@H?;P~xdR)-K_4dJ{Tu%sk;Eo9vz?~8-$o)Bj zMY!$?65R1v*GetV!}Zu;NlNP5U^cEN2BPhJ6D*GVb+8!jSHYazpA^iFduT8(?qR_k zxQ7I@;*S1zb>#oVFO!3i7zPI(*JA=7cS;c8cKLtcjtU~&=}cw`+y5PRH2S*qVTu1e zzA63>xLy8t?w5aQf&SYPvdlYp?r-k7H*iN`4M~{(o4Aww*KtSB+}`}>+*{9bzsr9L zca;CMd-56gq-*#7!(31FACdd?QvcGzDk=1(jZgNaj~M6QhC9K(26v2q8SZ%ha^gvR z=~>45*WpgY9$8W(y~&}RdrArV*W&(}W9ds~_&4EB!^V^J{cE4&U*yt$9=}cT&zC2B z=_|(j=ipBC&&8dDm9t+z^1r-E+a;C9;!g2rP@g~hM{_;VKMr@2e+=%S*zrkfq=!C& zt0|mI@jsAG?5#)g)(rm;+{ymFxYPUtNbk2eA;|6hd&F~UA}AQKK(^9n;&y$tY3HKD=l)O zPy3@}X`_^^?@HFSMUU1Qzk?;Zlx$Dj!#rAN{5S76+&8^nao_NM=KjBwwfC)*iuWbI zO!2o48%xtGMI6S8ykKFXJLpqDy$say`X+PJaDoUBY{udtgK`-c`7V zdeY+@=3Rq(h<7ROXzvcb0-Fr;9aViC?_Up(CzhKWkMVAFJjuJk@#uf;J3M+9>hvta zn&O>}+vS~!JIa&(X1aGe?h)P@xH3|UEiGC|)koIm_KxG1DW3E#U3_gI?;VXhkriWk z?^xVP-ch)ty%ULl63?ChkEZ|mFPa12%t%V6@bnaKDsGoI33seF0e6%)5qFX|8TT;n zFx;w6VV;+M=AT9aZ!mWzd%NOJ@OHr+;|;;>@^;2`{h+s-yIQdJHeaVbOY6P2b}PEr zrRcJ!{@+GxZy@hZ_BOzs#xA4Os`Nk;Jo*h{+6;G!w+(KWHvo6Mw-N4GZ*AO(-uk$c zymfI8^)|*m%#(iT5U-6p+S`=!nM`=tX2avXEgX;bwt~kI_STL^b0})SH;UuDO<<|- z9pQyzL#2@wRjPZ^v+N1!A1+6|USHT#xaZxKq3wx64}zca&G+PWM*Eo#d^E z+ucWcOW~X1EsfjdE$M#wCmrAGkZ@&Xk*5}RPc4W$%3B0?y0-xCKi3#NAoV||d$Ol{ za(3KF-W={pMlM$VDL>W}$MK!lezm>$I&~+$UEJ)y^f=P;XVj!em`u%5NA%9rQSC+C z30M)3)7o>mQ?MK-^|Wv5sP+QxSadgu<9XakwP$b-rEjN>YTA!HLTQdC-T#!++C@Au zg}qn_OWO5#In|3$F2tRLME#pF8;wv>bUf~q+6lO$kU4qhMBGU=X;+8VPQrDvTI=FU z#_XAQeg7{SB{QZGyfveCAns(&0g`eMnIDJEgp`A86=8-R=EE(elsJKCpW~MSd*4?1YeWNGtw5jWwX}lLX}oJr8Wqc z@{>`7{!8+|rh68NVzkon`+fF8{z~0HSi2Lw=*s`*d@SVc$!N5U-}Gk^QcAo>viB!t zJqzwQ`LcmBh;YZSlOpL6ouLa&Sjt*tdn|pj>MU(XG?6q}DfPY%k0SvWnYIy>m_KTi(|eoEv-2wg|?8RdImCvsKt z7OUlV`1f#qr~e?hGrfUaS5IBw*5mi`a_r7q=p{VzM5eDB6Mb2tZ6-5uYJ zdtZDX?o;toxX;DU;l2_74fmb+9o+Y0b`0Z>cpKk+tU>o$i{}Z-Be??BN_s{ib zU|}=d-wErQw!aqkH96->sg;rLu81Aa8)9Q4zkB!V?^xShj zdxNn(TMxNk!=vPC8~*?59F4vMBw?&#zCT-=$9Q+qzD&&k!CoU|eD2Yg%dL49`a^yDm&_v<~mnvHWs-mB9ex^R6L zhVR}B>@D9t>AR;AP6Jv_p2S|Fz-nXDTFlubqy!6!96OFp@Gm1N!lt5$Wyi*R0oB0? zCZr5Iiw4#n8}YuBgL!RixcQ2$AYmAk!3E6-<3v>1fDaJx$MeIb@=bgnR z<=AYjfaS<~Jh2cbmXHJNIF`qnWL@qo$f+Xa1lx+gU<-hz7`C=XeIeR*wDX)jFe2^h%v?OgV|?<+=~w z6}?oa9Y-(HY5JT&^9SFbzU$cMRGQzp_k8pl&)vy6HUGf(Z1gMcGtn=&Pe(uFJ{A3h z`(*SZ?i0}uxQ|EQ)4~_!+n~py?`RKIZ@g3OO7=JZ&6!EH|K(Xy(H-85|J_+}|LJ74 z|8!DVuvc(kFg}tqSJta9hh@}%JwZiIn>oBXQKtJem2;^%J4XfEr+;IkQ$PFvWD&)e zTPt>-TeSz@bX8|p`L$)}L8T9s)9gHVYSt_@Ia#h3`_^l5V&5^$tXA-TW}RR~cN)~X z?mWEp=?`D3ZQ#y?+Sr{5wMozp)~;>i&V<^IK6TI9ZtfJdp}|;IUw3z3!SCU$0`?NS zu-e}4EBN7()7nVRsyMthikn(>hii#$ zww(B|J+_-WdOLYLd%JkMGO7&mcJqc}(Yc4Wr#B26=e@DP*_ZKV1a_YLdk1(2GWv`} z+Zx4g${~zJW4&?CLg6rPf;W-TX)-pUQ@z8zX^d6V*>mZ_#`S0<;aG2mcO16UCoqnk z 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%0D1lG~DE2ff7BeoTnFxKM!4172W=IjHdV9zf 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 \ No newline at end of file diff --git a/templates/next-starter-with-examples/public/vercel.svg b/templates/next-starter-with-examples/public/vercel.svg new file mode 100644 index 000000000..d2f842227 --- /dev/null +++ b/templates/next-starter-with-examples/public/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/next-starter-with-examples/tailwind.config.ts b/templates/next-starter-with-examples/tailwind.config.ts new file mode 100644 index 000000000..2c80f0c3f --- /dev/null +++ b/templates/next-starter-with-examples/tailwind.config.ts @@ -0,0 +1,90 @@ +import type { Config } from "tailwindcss"; + +const config = { + darkMode: ["class"], + content: [ + "./pages/**/*.{ts,tsx}", + "./components/**/*.{ts,tsx}", + "./app/**/*.{ts,tsx}", + "./@/**/*.{ts,tsx}", + "./src/**/*.{ts,tsx}", + // js files primarily because in dist + "./node_modules/frames.js/dist/render/next/*.{ts,tsx,js,css}", + "./node_modules/frames.js/dist/render/*.{ts,tsx,js,css}", + "./node_modules/frames.js/dist/**/*.{ts,tsx,js,css}", + + // monorepo weirdness + "../../node_modules/frames.js/dist/render/next/*.{ts,tsx,js,css}", + "../../node_modules/frames.js/dist/render/*.{ts,tsx,js,css}", + "../../node_modules/frames.js/dist/**/*.{ts,tsx,js,css}", + ], + prefix: "", + theme: { + container: { + center: true, + padding: "2rem", + screens: { + "2xl": "1400px", + }, + }, + extend: { + colors: { + border: "hsl(var(--border))", + input: "hsl(var(--input))", + ring: "hsl(var(--ring))", + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", + primary: { + DEFAULT: "hsl(var(--primary))", + foreground: "hsl(var(--primary-foreground))", + }, + secondary: { + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", + }, + destructive: { + DEFAULT: "hsl(var(--destructive))", + foreground: "hsl(var(--destructive-foreground))", + }, + muted: { + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))", + }, + accent: { + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", + }, + popover: { + DEFAULT: "hsl(var(--popover))", + foreground: "hsl(var(--popover-foreground))", + }, + card: { + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", + }, + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", + }, + keyframes: { + "accordion-down": { + from: { height: "0" }, + to: { height: "var(--radix-accordion-content-height)" }, + }, + "accordion-up": { + from: { height: "var(--radix-accordion-content-height)" }, + to: { height: "0" }, + }, + }, + animation: { + "accordion-down": "accordion-down 0.2s ease-out", + "accordion-up": "accordion-up 0.2s ease-out", + }, + }, + }, + plugins: [require("tailwindcss-animate")], +} satisfies Config; + +export default config; diff --git a/templates/next-starter-with-examples/tsconfig.json b/templates/next-starter-with-examples/tsconfig.json new file mode 100644 index 000000000..26e4c0865 --- /dev/null +++ b/templates/next-starter-with-examples/tsconfig.json @@ -0,0 +1,47 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Default", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "esModuleInterop": true, + "incremental": false, + "isolatedModules": true, + "lib": [ + "es2022", + "DOM", + "DOM.Iterable" + ], + "module": "ESNext", + "moduleDetection": "force", + "moduleResolution": "Bundler", + "noEmit": true, + "noUncheckedIndexedAccess": true, + "plugins": [ + { + "name": "next", + }, + ], + "paths": { + "@/*": [ + "./@/*" + ] + }, + "jsx": "preserve", + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true, + "target": "ES2022", + "allowJs": true, + }, + "include": [ + "next-env.d.ts", + "next.config.js", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + ], + "exclude": [ + "node_modules" + ], +} \ No newline at end of file diff --git a/templates/next-utils-starter/.env.sample b/templates/next-utils-starter/.env.sample new file mode 100644 index 000000000..c85e4f5b8 --- /dev/null +++ b/templates/next-utils-starter/.env.sample @@ -0,0 +1 @@ +NEXT_PUBLIC_HOST="http://localhost:3000" \ No newline at end of file diff --git a/templates/next-utils-starter/.eslintrc.js b/templates/next-utils-starter/.eslintrc.js new file mode 100644 index 000000000..00e4aaad1 --- /dev/null +++ b/templates/next-utils-starter/.eslintrc.js @@ -0,0 +1,5 @@ +/** @type {import("eslint").Linter.Config} */ +module.exports = { + root: true, + extends: ["next"], +}; diff --git a/templates/next-utils-starter/.gitignore b/templates/next-utils-starter/.gitignore new file mode 100644 index 000000000..574e5471e --- /dev/null +++ b/templates/next-utils-starter/.gitignore @@ -0,0 +1,36 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz + +# testing +/coverage + +# next.js +.next +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts \ No newline at end of file diff --git a/templates/next-utils-starter/CHANGELOG.md b/templates/next-utils-starter/CHANGELOG.md new file mode 100644 index 000000000..a7f7fc853 --- /dev/null +++ b/templates/next-utils-starter/CHANGELOG.md @@ -0,0 +1,60 @@ +# utils-starter + +## 1.1.2 + +### Patch Changes + +- Updated dependencies [72e6617] +- Updated dependencies [7ccc562] + - frames.js@0.8.0 + +## 1.1.1 + +### Patch Changes + +- Updated dependencies [01fc5fe] +- Updated dependencies [60c6e56] +- Updated dependencies [e335829] +- Updated dependencies [eee74a9] + - frames.js@0.7.0 + +## 1.1.0 + +### Minor Changes + +- 845b30c: refactor: make frame validation errors arbitraty, remove unnecessary validateFrame function + +### Patch Changes + +- Updated dependencies [845b30c] +- Updated dependencies [ce1cec6] +- Updated dependencies [845b30c] + - frames.js@0.6.0 + +## 1.0.4 + +### Patch Changes + +- Updated dependencies [40d2662] + - frames.js@0.5.0 + +## 1.0.3 + +### Patch Changes + +- Updated dependencies [ccd3302] + - frames.js@0.4.0 + +## 1.0.2 + +### Patch Changes + +- Updated dependencies [03d041e] + - frames.js@0.3.0 + +## 1.0.1 + +### Patch Changes + +- Updated dependencies [608bac9] + - frames.js@0.2.0 diff --git a/templates/next-utils-starter/README.md b/templates/next-utils-starter/README.md new file mode 100644 index 000000000..415ff4eff --- /dev/null +++ b/templates/next-utils-starter/README.md @@ -0,0 +1,30 @@ +## Getting Started + +First, run the development server and debugger: + +```bash +yarn dev +``` + +This will also open the debugger in your browser. + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +To create [API routes](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) add an `api/` directory to the `app/` directory with a `route.ts` file. For individual endpoints, create a subfolder in the `api` directory, like `api/hello/route.ts` would map to [http://localhost:3000/api/hello](http://localhost:3000/api/hello). + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/templates/next-utils-starter/app/api/frame/route.tsx b/templates/next-utils-starter/app/api/frame/route.tsx new file mode 100644 index 000000000..186a3dcd9 --- /dev/null +++ b/templates/next-utils-starter/app/api/frame/route.tsx @@ -0,0 +1,46 @@ +import { + getFrameMessageFromRequestBody, + validateFrameMessage, +} from "frames.js"; +import { redirect } from "frames.js/core"; +import { createFrames, Button } from "frames.js/next"; + +const frames = createFrames(); + +const handleRequest = frames(async (ctx) => { + const body = await ctx.request.clone().json(); + + const untrustedMessage = getFrameMessageFromRequestBody(body); + + if (untrustedMessage.data?.frameActionBody?.buttonIndex === 2) { + return redirect(new URL("/redirect", ctx.url), { status: 302 }); + } + + const result = await validateFrameMessage(body); + + const { isValid, message } = result; + + if (!isValid || !message) { + return { + image: Invalid message, + }; + } + + const randomInt = Math.floor(Math.random() * 100); + const imageUrl = `https://picsum.photos/seed/${randomInt}/1146/600`; + + return { + image: imageUrl, + buttons: [ + , + , + ], + }; +}); + +export const GET = handleRequest; +export const POST = handleRequest; diff --git a/templates/next-utils-starter/app/constants.ts b/templates/next-utils-starter/app/constants.ts new file mode 100644 index 000000000..05758ac4b --- /dev/null +++ b/templates/next-utils-starter/app/constants.ts @@ -0,0 +1,6 @@ +export const HOST = process.env["NEXT_PUBLIC_HOST"] || "http://localhost:3000"; + +export const ogImage = `${HOST}/image.png`; +export const frameImage = `${HOST}/image_frame.png`; +export const frameImageFlipped = `${HOST}/image_frame_flipped.png`; +export const framePostUrl = `${HOST}/api/frame`; diff --git a/templates/next-utils-starter/app/favicon.ico b/templates/next-utils-starter/app/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..3f804c026c253d52f61b6f70ec351d1044e6bd8a GIT binary patch literal 8267 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 a5CHzt!@LfZ#gcC&0Cki$vQpVR{Qm$*Br?$e literal 0 HcmV?d00001 diff --git a/templates/next-utils-starter/app/layout.tsx b/templates/next-utils-starter/app/layout.tsx new file mode 100644 index 000000000..11369f8f6 --- /dev/null +++ b/templates/next-utils-starter/app/layout.tsx @@ -0,0 +1,33 @@ +import { fetchMetadata } from "frames.js/next"; +import type { Metadata } from "next"; +import { Inter } from "next/font/google"; +import { framePostUrl, ogImage } from "./constants"; + +const inter = Inter({ subsets: ["latin"] }); + +export const metadata: Metadata = { + title: "Random Image Frame", + description: "This is an example of a simple frame using frames.js", + openGraph: { + images: [ + { + url: ogImage, + }, + ], + }, + other: { + ...(await fetchMetadata(new URL("/frames", framePostUrl))), + }, +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}): JSX.Element { + return ( + + {children} + + ); +} diff --git a/templates/next-utils-starter/app/page.module.css b/templates/next-utils-starter/app/page.module.css new file mode 100644 index 000000000..98481c6a2 --- /dev/null +++ b/templates/next-utils-starter/app/page.module.css @@ -0,0 +1,335 @@ +.main { + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + padding: 6rem; + min-height: 100vh; +} + +.vercelLogo { + filter: invert(1); +} + +.description { + display: inherit; + justify-content: inherit; + align-items: inherit; + font-size: 0.85rem; + max-width: var(--max-width); + width: 100%; + z-index: 2; + font-family: var(--font-mono); +} + +.description a { + display: flex; + justify-content: center; + align-items: center; + gap: 0.5rem; +} + +.description p { + position: relative; + margin: 0; + padding: 1rem; + background-color: rgba(var(--callout-rgb), 0.5); + border: 1px solid rgba(var(--callout-border-rgb), 0.3); + border-radius: var(--border-radius); +} + +.code { + font-weight: 700; + font-family: var(--font-mono); +} + +.hero { + display: flex; + position: relative; + place-items: center; +} + +.heroContent { + display: flex; + position: relative; + z-index: 0; + padding-bottom: 4rem; + flex-direction: column; + gap: 2rem; + justify-content: space-between; + align-items: center; + width: auto; + font-family: system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, + "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", + "Segoe UI Symbol", "Noto Color Emoji"; + padding-top: 48px; + + @media (min-width: 768px) { + padding-top: 4rem; + padding-bottom: 6rem; + } + @media (min-width: 1024px) { + padding-top: 5rem; + padding-bottom: 8rem; + } +} + +.logos { + display: flex; + z-index: 50; + justify-content: center; + align-items: center; + width: 100%; +} + +.grid { + display: grid; + grid-template-columns: repeat(4, minmax(25%, auto)); + max-width: 100%; + width: var(--max-width); +} + +.card { + padding: 1rem 1.2rem; + border-radius: var(--border-radius); + background: rgba(var(--card-rgb), 0); + border: 1px solid rgba(var(--card-border-rgb), 0); + transition: background 200ms, border 200ms; +} + +.card span { + display: inline-block; + transition: transform 200ms; +} + +.card h2 { + font-weight: 600; + margin-bottom: 0.7rem; +} + +.card p { + margin: 0; + opacity: 0.6; + font-size: 0.9rem; + line-height: 1.5; + max-width: 30ch; +} + +@media (prefers-reduced-motion) { + .card:hover span { + transform: none; + } +} + +/* Mobile */ +@media (max-width: 700px) { + .content { + padding: 4rem; + } + + .grid { + grid-template-columns: 1fr; + margin-bottom: 120px; + max-width: 320px; + text-align: center; + } + + .card { + padding: 1rem 2.5rem; + } + + .card h2 { + margin-bottom: 0.5rem; + } + + .center { + padding: 8rem 0 6rem; + } + + .center::before { + transform: none; + height: 300px; + } + + .description { + font-size: 0.8rem; + } + + .description a { + padding: 1rem; + } + + .description p, + .description div { + display: flex; + justify-content: center; + position: fixed; + width: 100%; + } + + .description p { + align-items: center; + inset: 0 0 auto; + padding: 2rem 1rem 1.4rem; + border-radius: 0; + border: none; + border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25); + background: linear-gradient( + to bottom, + rgba(var(--background-start-rgb), 1), + rgba(var(--callout-rgb), 0.5) + ); + background-clip: padding-box; + backdrop-filter: blur(24px); + } + + .description div { + align-items: flex-end; + pointer-events: none; + inset: auto 0 0; + padding: 2rem; + height: 200px; + background: linear-gradient( + to bottom, + transparent 0%, + rgb(var(--background-end-rgb)) 40% + ); + z-index: 1; + } +} + +/* Enable hover only on non-touch devices */ +@media (hover: hover) and (pointer: fine) { + .card:hover { + background: rgba(var(--card-rgb), 0.1); + border: 1px solid rgba(var(--card-border-rgb), 0.15); + } + + .card:hover span { + transform: translateX(4px); + } +} + +.circles { + position: absolute; + min-width: 614px; + min-height: 614px; + pointer-events: none; +} + +.logo { + z-index: 50; + width: 120px; + height: 120px; +} + +.logoGradientContainer { + display: flex; + position: absolute; + z-index: 50; + justify-content: center; + align-items: center; + width: 16rem; + height: 16rem; +} + +.turborepoWordmarkContainer { + display: flex; + z-index: 50; + padding-left: 1.5rem; + padding-right: 1.5rem; + flex-direction: column; + gap: 1.25rem; + justify-content: center; + align-items: center; + text-align: center; + + @media (min-width: 1024px) { + gap: 1.5rem; + } +} + +.turborepoWordmark { + width: 160px; + fill: white; + + @media (min-width: 768px) { + width: 200px; + } +} + +.code { + font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", + monospace; + font-weight: 700; +} + +/* Tablet and Smaller Desktop */ +@media (min-width: 701px) and (max-width: 1120px) { + .grid { + grid-template-columns: repeat(2, 50%); + } +} + +/* Gradients */ +.gradient { + position: absolute; + mix-blend-mode: normal; + will-change: filter; + pointer-events: none; +} + +.gradientSmall { + filter: blur(32px); +} + +.gradientLarge { + filter: blur(75px); +} + +.glowConic { + background-image: var(--glow-conic); +} + +.logoGradient { + opacity: 0.9; + width: 120px; + height: 120px; +} + +.backgroundGradient { + top: -500px; + width: 1000px; + height: 1000px; + opacity: 0.15; +} + +.button { + background-color: #ffffff; + border-radius: 8px; + border-style: none; + box-sizing: border-box; + color: #000000; + cursor: pointer; + display: inline-block; + font-size: 16px; + height: 40px; + line-height: 20px; + list-style: none; + margin: 0; + outline: none; + padding: 10px 16px; + position: relative; + text-align: center; + text-decoration: none; + transition: color 100ms; + vertical-align: baseline; + user-select: none; + -webkit-user-select: none; + touch-action: manipulation; +} + +.button:hover, +.button:focus { + background-color: #e5e4e2; +} diff --git a/templates/next-utils-starter/app/page.tsx b/templates/next-utils-starter/app/page.tsx new file mode 100644 index 000000000..c4d0364a1 --- /dev/null +++ b/templates/next-utils-starter/app/page.tsx @@ -0,0 +1,3 @@ +export default function Page(): JSX.Element { + return

Example
; +} diff --git a/templates/next-utils-starter/next.config.js b/templates/next-utils-starter/next.config.js new file mode 100644 index 000000000..d1e4e084a --- /dev/null +++ b/templates/next-utils-starter/next.config.js @@ -0,0 +1,2 @@ +/** @type {import('next').NextConfig} */ +module.exports = {}; diff --git a/templates/next-utils-starter/package.json b/templates/next-utils-starter/package.json new file mode 100644 index 000000000..4b67d3d75 --- /dev/null +++ b/templates/next-utils-starter/package.json @@ -0,0 +1,31 @@ +{ + "name": "template-next-utils-starter", + "version": "1.1.2", + "private": true, + "scripts": { + "dev": "concurrently --kill-others \"next dev\" \"frames --url http://localhost:3000\"", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "frames.js": "^0.9.1", + "next": "^14.0.4", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@next/eslint-plugin-next": "^14.0.4", + "@frames.js/debugger": "^0.1.8", + "@types/eslint": "^8.56.1", + "@types/node": "^20.10.6", + "@types/react": "^18.2.46", + "@types/react-dom": "^18.2.18", + "concurrently": "^8.2.2", + "eslint": "^8.56.0", + "typescript": "^5.3.3" + }, + "engines": { + "node": ">=18.17.0" + } +} diff --git a/templates/next-utils-starter/public/image.png b/templates/next-utils-starter/public/image.png new file mode 100644 index 0000000000000000000000000000000000000000..91777b90e0e116c7e579de93eb42715132aa7857 GIT binary patch literal 88230 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 z zlk7s9c&f6C9}WJeffG=W-&O#90BQjG;13kREPz=6vjAq{j{;y8{>NF63_6%~lOq7m z4VK2&tH!H_>ivF>n44!VwM0Pe?bF=qQq$ma>_G0MK>0?o!}vxo#A7OJb9%bB&Z9Bi z4P!q!GX6;yz&fq&IkO7n`8T2#AyBJ6?mTXIeSNwc90^$4j|;<*aEblK6Tjen-08_~ z7S7y4uzZ?rkCWh&mt?6~>ZZVTL5s}4c!vOyhuH_v*;u=TT(o+wnf%FTXcw6j}^wIA+(=vw8LmL}XF zPtt5r*>ijJ;>#Ds6=YG1>k!1w*4Z75Yq>kd&z#V+I;+ZU%Dn1uw6=FSd&z%$d%>Kg zA3oJ5R-VznPX=s!I1N^)hCp^c2QD2R<0gB2ec`9JkmCp){2ATAhFby*7<0LXOsK-? z*Au&pPmQ%{IBzM;N&{iD#a_1F?qQ5uqpv^8Bg7$Xf7;64WUst9Bc5(1c4GARV?qCE zo)A)#-%kPkX&RTn38(=8fEs`r{3ZhEga7XutO>E5Iu=F&p~AJ3?hs5>@A|qEt3rTF z@Lmh$B23}jddmOcg~{lSK#YeLFmv9r-dp&oMz-%_IP8E1%dsJU9UmSov`J-+q?O7O z-1W%lKkxt8>tC0))SbOp-p1xIY1Q8&gdztHJT5+b`Ek0Bg#%`7*mtr_04~X5-?Xng zUo68y0heWUFi8%eRjQkG*UcNkPEGaI7Vk;|?N|Fsf=mRN_(uUS3;%mrIDi;4vCf>yiv0c)WI$6@ LSEX3VI{d!?gkMfG literal 0 HcmV?d00001 diff --git a/templates/next-utils-starter/public/image_frame_flipped.png b/templates/next-utils-starter/public/image_frame_flipped.png new file mode 100644 index 0000000000000000000000000000000000000000..b2cab28d8464375ef10cf7b068325fcf23505f20 GIT binary patch literal 78712 zcmeHQ2{e^`w?F2HXfmWYq!bxSWylzjN+ffpLXvqt=CLS+63TE+vt%kMvtvk*`#R^Y)xF=kYqKnm=ltjA+5f%w@3;Tk6}6K}40K!QP$(3G@=*nK z6pAh#g`$dCLyg?Y?=)jVq3C5Tk?84z}kltjtiTqgNueX>?A%WyYSl87_O_ z-f`M|TJ8hBx0v)$eFhqbH=u8^QplAWGH=$;)hWE3dUcnM1@op;d-hz-7h=}9<^0@O zyY-=O>fF1jp1GbXpC$1LoJemK!Gi|%a^uz;yBIZT&_+7DLK$f9@+Lg|q^#<Y(xxij}rp_bkaXZQ))#JFz=1dQcJ>L`Dj8aqYuzRhGdSd7=nI9ZW zbwFc|%VonjY-MwDQ_nm36$9tQEc7{Kx$K z$xm^ZH!a->T{0M-;E|V3Hr9O09Q5W`Fa3mzh^u zDL|_d-u&P)ft>k0+XugfD`m9wK@Ciu#%B#p1O2PZH&MRey39`*&$r98Og@=rjN4mI zEw1={2u3}*m_-k_`~2R`^SYrrJ=*;P1w5jDi64C8E6w@8?XB$`oaPDM&2(lH?S}1K zT9+E0qeTVv&x$-2i`^`4x;^Ukv93&Cu_z&W+VBCBBX>I6buM{Xco%)}d@j&P?(&eF zbJzP&#>ie8%Pt4gv65`#=;_1fi^JF9(cgj8x8`pOD-x}z;bHDg2#w`wGzm9j09tUH=Rs|IE8cHX$ z-vNpfmpr_K7pjE0 zHr_Mlk>}{UC?EA2eGa|%7VC+OQU*IC0(+RRwvSG{J@v5o{;-knfxLl&#qz}m4vTiw zDHKVLsh$d@YEhHXxe;=W)6wsYoQkLFE^=VtrE4&>NQ_V=1i{+u%51t zYTzD3*M-Kvt~#sqoLaU_@0nsU#i5<0B}oI%t(+O$LLy5e);d!zjf#FVeROA!-BbI1 z=UMI%{x7PL1rNw9Z(fMe36C^5YF;cvj;msJ*rxO;K0eL>74B{HB`r;KZ~6%J{hG1( z*d-d2v_L>WfKq|uSpn4Gly5V>?~r+kFK(R~s_LNqj!tgzpyNW6(@|;xhg3LODIAR{ zdb{Weexjo^a%g%5KTJ6J&cd%RIwV*Eb{kXQUVBWIO=n%5FN3j21GS4^emm*{N~uWM zj#?iTU3kEbCKbyuO8zatwOzy?%@cU_1C!Tl%I6A$>&*lGrn%*gQf>%&i0(Ve%&ovv zPH!r$emPm;Ao|RWi>5N40^<~_xD3h#zL0$i$y1cR$NJR&;yuMDnDHBQv=fwO!(9?85^c{Nb~7m_8Ggi3e2DwT6Zwpt?uGfc55MO+$t%cZ!&A3j zl_@tkESQ34gEG!kb)4(S4Y7xZ)oCrHEEp3nIo}7eNzh2m zIMbK)$?Q?WG2GjJ)8pwZ;#c2qSKThO-IiB0Lg=PPId1osO_o;~cVKVI-#ME5QUyEP+&=Z$a zDXQ_wHjk>*d!JORr>WVhzIW7 zoF9c_#IGOe`qWeNs^(;kdq%Kcot{<7)|7oI`Fins3r#UisZCd!PQT>O2(xeDKwZCKomZOZ;cBC>H0`I_39c$55z+=SM`g5qE_nwm zN>LCBtI%(ZuNLhLsG;`So}q{dYY*ME&EEL6wfyG~Rl;?4IUNT})|HTLH+jIc{l-W4 z2d5Ri-blPzd?WrQ>3SIZRLqAHo+^|(lT`FhU~69Xop9&y+LnL4)%N0rEf@Lrwp?to zm~DLDw5P}ls~g`a<#<)RM6$;7rCX94{?e6Foe(zW1I(EMZ=>idtSVkc4MmNlB&Xa= zX4X5PBlV*0#rZQVXX_)R@%?5)ErJokt_A~Qf6;{!T(b}osQ$6cdQbk)X*qF31=e*4E za-Ond$*s?sa@WB;^w4l87+=_XpY1rSxfCsy4EsVV%-#E&!xY~)iT26p%mCNaDVq^< zljO3|GAquB^0N0qT`y`AnxltfhjU9ao2x&Eb!m4`eP|=#dhsPoyKAEEln_ch+1fXu z*NJT%#dep*yp>oVOm&$uirR(Rf_ev~^_m<`E9SV(`Wp$Hoy_~Bz9{VC+AryJEe|)Ii1*5ts;CoT(qM> z;pLUMD>OBR z8)|U(V+RkoRetfd&%!8?sS6j}eXh24vE22j6%YO>$EF!(%}rjnZ;ExdYg|t(PTW>A z_*ek@Jwq&OI{12b&WkQSl$oc*|^WVUjH3|kd3c) zjLCFpZJtq{h-G0Fxc#F2qYxMV^Q|XQ!N+a(d^5~)TVHVW*%Qa-6`hkI_{i~N)zRXS zkm6{>T(~&f|Ebot z{)E0`D&eK)gx)*7w@t&&>j$>fpGh_-@g@&5ew=d3hVn$}N?ohFuFA!rhdXT9E8s+gFj3_R1(0f5|8J&}|v9 zU7f+==|*JqTKh#d`qm#JyZaa=8_+BAPHbjIRf}onj^^b;pW<$)c~n_abIcf46`FW?jRE$phPEDCT3iWgHiorm6+P zpXT`EntjOb#e0Tn@0rj?T#6_&9p&>XDkwhWdJT$-Yy*k{xgtZpQDj?CR4dmg)G;#l ze_X4R?fOxM9EA$9KvDiEqlf%n{t8EaklH_fQ{23aqCx)JfcymBCI7QDUHV;$Kd-4` zkk3$Zr{$HEk>96H9L&sY952{9nfTG?A~$I5j_Nw1P|Q1)f5?>8c}7tv@W~a=m<8h#S39#K}^M zTSr9=EpO{!hCV1LEGWz^O@~IKB^^x9OQ?Fm_ zz1-11zWx}e8OGvgPd1J}riDyUX!#SNy@J9*e^<@P;{3m;w*1K-)mG;9M|YCTjY+6k zV9cy^6)dcgrACG(y?4LJe#w=7{@X`CN4l!2&Z?^7d&O2)UG>plt7LYb#C1bBh~s z>Sa;N3UV44vOxmgrj=$}X-6A-0_`zwNm_d7tTBH>Hj<7f)Os-LxG|=>tlIL($y-Hj6I+kVG)j;6_0=SZ2C^i4A#JF1Y_s!>CxUIGB@ipQaxli#e|mi zMfuI`w98qDneCizuBZ-kZJj9^8)#dY$9$W<-c?&sk=EKK%HT%3T(nS}PT#`?lU_#RIQ3%EXcy)uqKu^+{+Ee6b9&_-PWx1vNE9M?*9G7 zK}vdEQFn(O|Gv~eHHqdmE{{plKrheu*Bz{sDZK2UfiGw^BF01yB`0004io&kCW=o#^l zBS6joIRoSjJPq(Pz|#=#Y{>$-3FIb_n-CEI5djbp01*L1lUoo*17S1}Mgy^D5PJr( zXC#F9LBJ*iY(l^$L^(s0GekN6ZQS_ZBXxaNL<_W`~UYKjOHvX%<7vpSb}3)+vOe&v5h^@&!P?0LT{rNj8Y~h-Ckt zCE4(+31JbkIe5}}#lV@Dp|Y{D30=-?)8F4e{Ut&*bgI>3Wcurauu$`Atk>k(;l;L< z)HTCtg?-=I>}N_@$|5pbB?{&uT*ES3z2`8qJ+WoAN!msa;!aMnC^;-ItXQfMUK%Uu z<2~Qq6&5BlKh9DXjq`Swbf2HjDkyj?zfAv4>9r3J1jcq1^%afvkJpZs*v@~Q?sN5a z@f_%EE|W=Hw3n33w@-5p!Bz>Pr?d7$~* zMbpnGZN5fi3Xo+C!LAjd;(A-c27Z~#WR>}$i#U{4Fa1f$9a43sFnls^&VJjfW`2cX zp!t!EJ1JVi#J|_Rg>GwE)3L5HsoP1w)lI4BbzjudDU!h8irFGdFfm-_{Hr;vYSS+n zNgwh`uZWbD?iDaDcW+(D3MJu@hHpla?r8C|lCaY4dB_q}=W^DQ@<`K>H>dF;6)7tn zmx&}qa+~UsAmNe9Y9VQN&ZHQVveFaG!lqIq-ug^rUU?;iU9WPRwjzf8{%QP27P8}Tbd(ldYmKKu$1beG@0 z4L2Zi-tzl*;bvr~YyRzSRgF6mnVt<>!qk z1*0pnbMwU+(>SXW@II18Zf+jlqn$mH9^OkhnUUE!j%5sXG?2>1wz|8ew|BTFZc1ih z&~qqSsM=$sEl!)UzCLIm&22fzqOgV;voPz>x-c|(pd+GUru{+l#C$$WZ+!0vwrpT- zE#nFTZ0G3c!C|=AMQCfos>(vjP+Ne4+!*vKLTa}$(peTtyEQzg_!Alu=j*aJKc`wcO z^bG3@+P+fp*20<7BE{a3PjULp9}&k{txQLTDs@TOX+dczsUpeIm7_|vU~zDMGX9!SjCw`KYr+Et*83+vs4G0a98`H7~gV2Dc0Zjv% z2Fx=s&xkh9eZf2fp9Xvy@M!=D03ZN>0OB(<0(u7M8K7qXIRoSjkTdZ(JwgWoPXjy+ z@HGFCTky00;me0Du4h0ssgg-lm0P0&unl&ep)$n*Y@UY4aflhaQt5{0(bQ+ku13 z>NIMGL=v-1%yy;>VcSVL2-U7zcw^GdpoPdDR*rF;B~z*!6}wLgUyh~Ps*9_yCFL9p zOa`6|yk;OXu$z(auLxjk20a570GKmin-PBo01QnqG{MjWLlX>5Ff{*NLim5mF9d)F zKuv&~0SE|)Ch=?5Ff_r?1Va-HO`?-%0u2Z>Akct7 z10pn_a7GUP&s+e2ZW0;h29zLBfYDkVTfwUxc;tdbkb{z!c#ccgZtfpSZLCg?kHJ+10ih&o3 z { + return { + image: ctx.message ? ( +
+ GM, {ctx.message.requesterUserData?.displayName}! Your FID is{" "} + {ctx.message.requesterFid} + {", "} + {ctx.message.requesterFid < 20_000 + ? "you're OG!" + : "welcome to the Farcaster!"} +
+ ) : ( +
+ Say GM +
+ ), + buttons: ctx.url.searchParams.has("saidGm") + ? [ + , + ] + : [], + }; +}); + +export const GET = handleRequest; +export const POST = handleRequest; diff --git a/templates/next/app/globals.css b/templates/next/app/globals.css new file mode 100644 index 000000000..8e0bb857b --- /dev/null +++ b/templates/next/app/globals.css @@ -0,0 +1,11 @@ +* { + box-sizing: border-box; + padding: 0; + margin: 0; +} + +html, +body { + max-width: 100vw; + overflow-x: hidden; +} \ No newline at end of file diff --git a/templates/next/app/layout.tsx b/templates/next/app/layout.tsx new file mode 100644 index 000000000..3314e4780 --- /dev/null +++ b/templates/next/app/layout.tsx @@ -0,0 +1,22 @@ +import type { Metadata } from "next"; +import { Inter } from "next/font/google"; +import "./globals.css"; + +const inter = Inter({ subsets: ["latin"] }); + +export const metadata: Metadata = { + title: "Create Next App", + description: "Generated by create next app", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + {children} + + ); +} diff --git a/templates/next/app/page.tsx b/templates/next/app/page.tsx new file mode 100644 index 000000000..0c8f292b2 --- /dev/null +++ b/templates/next/app/page.tsx @@ -0,0 +1,17 @@ +import { fetchMetadata } from "frames.js/next"; +import { Metadata } from "next"; + +export async function generateMetadata(): Promise { + return { + title: "Frames Next.js Example", + other: { + ...(await fetchMetadata( + new URL("/frames", process.env.VERCEL_URL || "http://localhost:3000") + )), + }, + }; +} + +export default async function Home() { + return
GM user data example.
; +} diff --git a/templates/next/next.config.js b/templates/next/next.config.js new file mode 100644 index 000000000..4678774e6 --- /dev/null +++ b/templates/next/next.config.js @@ -0,0 +1,4 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = {}; + +export default nextConfig; diff --git a/templates/next/package.json b/templates/next/package.json new file mode 100644 index 000000000..312b615a0 --- /dev/null +++ b/templates/next/package.json @@ -0,0 +1,26 @@ +{ + "name": "template-next", + "version": "0.0.0", + "private": true, + "type": "module", + "dependencies": { + "frames.js": "^0.9.1", + "next": "^14.1.2", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/node": "^18.17.0", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "@frames.js/debugger": "^0.1.8", + "concurrently": "^8.2.2", + "typescript": "^5.3.3" + }, + "scripts": { + "dev": "concurrently \"next dev\" \"frames --url http://localhost:3000\"", + "start": "next start", + "build": "next build", + "lint": "next lint" + } +} diff --git a/templates/next/public/next.svg b/templates/next/public/next.svg new file mode 100644 index 000000000..5174b28c5 --- /dev/null +++ b/templates/next/public/next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/next/public/vercel.svg b/templates/next/public/vercel.svg new file mode 100644 index 000000000..d2f842227 --- /dev/null +++ b/templates/next/public/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/next/tsconfig.json b/templates/next/tsconfig.json new file mode 100644 index 000000000..862143548 --- /dev/null +++ b/templates/next/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next", + }, + ], + "paths": { + "@/*": ["./*"], + }, + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"], +} diff --git a/turbo.json b/turbo.json index 0b9281649..21ba5d5de 100644 --- a/turbo.json +++ b/turbo.json @@ -15,6 +15,7 @@ } }, "globalEnv": [ + "NODE_ENV", "NEXT_PUBLIC_HOST", "FARCASTER_DEVELOPER_FID", "FARCASTER_DEVELOPER_MNEMONIC" diff --git a/yarn.lock b/yarn.lock index 1782f060c..31d91e21c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1636,11 +1636,23 @@ "@motionone/dom" "^10.16.4" tslib "^2.3.1" +"@next/env@14.1.0": + version "14.1.0" + resolved "https://registry.yarnpkg.com/@next/env/-/env-14.1.0.tgz#43d92ebb53bc0ae43dcc64fb4d418f8f17d7a341" + integrity sha512-Py8zIo+02ht82brwwhTg36iogzFqGLPXlRGKQw5s+qP/kMNc4MAyDeEwBKDijk6zTIbegEgu8Qy7C1LboslQAw== + "@next/env@14.1.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/env/-/env-14.1.4.tgz#432e80651733fbd67230bf262aee28be65252674" integrity sha512-e7X7bbn3Z6DWnDi75UWn+REgAbLEqxI8Tq2pkFOFAMpWAWApz/YCUhtWMWn410h8Q2fYiYL7Yg5OlxMOCfFjJQ== +"@next/eslint-plugin-next@14.1.0": + version "14.1.0" + resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-14.1.0.tgz#29b041233fac7417e22eefa4146432d5cd910820" + integrity sha512-x4FavbNEeXx/baD/zC/SdrvkjSby8nBn8KcCREqk6UuwvwoAPZmaV8TFCAuo/cpovBRTIY67mHhe86MQQm/68Q== + dependencies: + glob "10.3.10" + "@next/eslint-plugin-next@14.1.4", "@next/eslint-plugin-next@^14.0.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-14.1.4.tgz#d7372b5ffede0e466af8af2ff534386418827fc8" @@ -1648,46 +1660,91 @@ dependencies: glob "10.3.10" +"@next/swc-darwin-arm64@14.1.0": + version "14.1.0" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.0.tgz#70a57c87ab1ae5aa963a3ba0f4e59e18f4ecea39" + integrity sha512-nUDn7TOGcIeyQni6lZHfzNoo9S0euXnu0jhsbMOmMJUBfgsnESdjN97kM7cBqQxZa8L/bM9om/S5/1dzCrW6wQ== + "@next/swc-darwin-arm64@14.1.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.4.tgz#a3bca0dc4393ac4cf3169bbf24df63441de66bb7" integrity sha512-ubmUkbmW65nIAOmoxT1IROZdmmJMmdYvXIe8211send9ZYJu+SqxSnJM4TrPj9wmL6g9Atvj0S/2cFmMSS99jg== +"@next/swc-darwin-x64@14.1.0": + version "14.1.0" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.0.tgz#0863a22feae1540e83c249384b539069fef054e9" + integrity sha512-1jgudN5haWxiAl3O1ljUS2GfupPmcftu2RYJqZiMJmmbBT5M1XDffjUtRUzP4W3cBHsrvkfOFdQ71hAreNQP6g== + "@next/swc-darwin-x64@14.1.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.4.tgz#ba3683d4e2d30099f3f2864dd7349a4d9f440140" integrity sha512-b0Xo1ELj3u7IkZWAKcJPJEhBop117U78l70nfoQGo4xUSvv0PJSTaV4U9xQBLvZlnjsYkc8RwQN1HoH/oQmLlQ== +"@next/swc-linux-arm64-gnu@14.1.0": + version "14.1.0" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.0.tgz#893da533d3fce4aec7116fe772d4f9b95232423c" + integrity sha512-RHo7Tcj+jllXUbK7xk2NyIDod3YcCPDZxj1WLIYxd709BQ7WuRYl3OWUNG+WUfqeQBds6kvZYlc42NJJTNi4tQ== + "@next/swc-linux-arm64-gnu@14.1.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.4.tgz#3519969293f16379954b7e196deb0c1eecbb2f8b" integrity sha512-457G0hcLrdYA/u1O2XkRMsDKId5VKe3uKPvrKVOyuARa6nXrdhJOOYU9hkKKyQTMru1B8qEP78IAhf/1XnVqKA== +"@next/swc-linux-arm64-musl@14.1.0": + version "14.1.0" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.0.tgz#d81ddcf95916310b8b0e4ad32b637406564244c0" + integrity sha512-v6kP8sHYxjO8RwHmWMJSq7VZP2nYCkRVQ0qolh2l6xroe9QjbgV8siTbduED4u0hlk0+tjS6/Tuy4n5XCp+l6g== + "@next/swc-linux-arm64-musl@14.1.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.4.tgz#4bb3196bd402b3f84cf5373ff1021f547264d62f" integrity sha512-l/kMG+z6MB+fKA9KdtyprkTQ1ihlJcBh66cf0HvqGP+rXBbOXX0dpJatjZbHeunvEHoBBS69GYQG5ry78JMy3g== +"@next/swc-linux-x64-gnu@14.1.0": + version "14.1.0" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.0.tgz#18967f100ec19938354332dcb0268393cbacf581" + integrity sha512-zJ2pnoFYB1F4vmEVlb/eSe+VH679zT1VdXlZKX+pE66grOgjmKJHKacf82g/sWE4MQ4Rk2FMBCRnX+l6/TVYzQ== + "@next/swc-linux-x64-gnu@14.1.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.4.tgz#1b3372c98c83dcdab946cdb4ee06e068b8139ba3" integrity sha512-BapIFZ3ZRnvQ1uWbmqEGJuPT9cgLwvKtxhK/L2t4QYO7l+/DxXuIGjvp1x8rvfa/x1FFSsipERZK70pewbtJtw== +"@next/swc-linux-x64-musl@14.1.0": + version "14.1.0" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.0.tgz#77077cd4ba8dda8f349dc7ceb6230e68ee3293cf" + integrity sha512-rbaIYFt2X9YZBSbH/CwGAjbBG2/MrACCVu2X0+kSykHzHnYH5FjHxwXLkcoJ10cX0aWCEynpu+rP76x0914atg== + "@next/swc-linux-x64-musl@14.1.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.4.tgz#8459088bdc872648ff78f121db596f2533df5808" integrity sha512-mqVxTwk4XuBl49qn2A5UmzFImoL1iLm0KQQwtdRJRKl21ylQwwGCxJtIYo2rbfkZHoSKlh/YgztY0qH3wG1xIg== +"@next/swc-win32-arm64-msvc@14.1.0": + version "14.1.0" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.0.tgz#5f0b8cf955644104621e6d7cc923cad3a4c5365a" + integrity sha512-o1N5TsYc8f/HpGt39OUQpQ9AKIGApd3QLueu7hXk//2xq5Z9OxmV6sQfNp8C7qYmiOlHYODOGqNNa0e9jvchGQ== + "@next/swc-win32-arm64-msvc@14.1.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.4.tgz#84280a08c00cc3be24ddd3a12f4617b108e6dea6" integrity sha512-xzxF4ErcumXjO2Pvg/wVGrtr9QQJLk3IyQX1ddAC/fi6/5jZCZ9xpuL9Tzc4KPWMFq8GGWFVDMshZOdHGdkvag== +"@next/swc-win32-ia32-msvc@14.1.0": + version "14.1.0" + resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.0.tgz#21f4de1293ac5e5a168a412b139db5d3420a89d0" + integrity sha512-XXIuB1DBRCFwNO6EEzCTMHT5pauwaSj4SWs7CYnME57eaReAKBXCnkUE80p/pAZcewm7hs+vGvNqDPacEXHVkw== + "@next/swc-win32-ia32-msvc@14.1.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.4.tgz#23ff7f4bd0a27177428669ef6fa5c3923c738031" integrity sha512-WZiz8OdbkpRw6/IU/lredZWKKZopUMhcI2F+XiMAcPja0uZYdMTZQRoQ0WZcvinn9xZAidimE7tN9W5v9Yyfyw== +"@next/swc-win32-x64-msvc@14.1.0": + version "14.1.0" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.0.tgz#e561fb330466d41807123d932b365cf3d33ceba2" + integrity sha512-9WEbVRRAqJ3YFVqEZIxUqkiO8l1nool1LmNxygr5HWF8AcSYsEpneUDhmjUVJEzO2A04+oPtZdombzzPPkTtgg== + "@next/swc-win32-x64-msvc@14.1.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.4.tgz#bccf5beccfde66d6c66fa4e2509118c796385eda" @@ -5759,6 +5816,21 @@ escape-string-regexp@^5.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== +eslint-config-next@14.1.0: + version "14.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-14.1.0.tgz#7e309d426b8afacaba3b32fdbb02ba220b6d0a97" + integrity sha512-SBX2ed7DoRFXC6CQSLc/SbLY9Ut6HxNB2wPTcoIWjUMd7aF7O/SIE7111L8FdZ9TXsNV4pulUDnfthpyPtbFUg== + dependencies: + "@next/eslint-plugin-next" "14.1.0" + "@rushstack/eslint-patch" "^1.3.3" + "@typescript-eslint/parser" "^5.4.2 || ^6.0.0" + eslint-import-resolver-node "^0.3.6" + eslint-import-resolver-typescript "^3.5.2" + eslint-plugin-import "^2.28.1" + eslint-plugin-jsx-a11y "^6.7.1" + eslint-plugin-react "^7.33.2" + eslint-plugin-react-hooks "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" + eslint-config-next@^14.1.0: version "14.1.4" resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-14.1.4.tgz#22f2ba4c0993e991249d863656a64c204bae542c" @@ -6333,7 +6405,7 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.2.9, fast-glob@^3.3.0, fast-glob@^3.3.1: +fast-glob@^3.2.9, fast-glob@^3.3.0, fast-glob@^3.3.1, fast-glob@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== @@ -6514,6 +6586,17 @@ fraction.js@^4.3.7: resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7" integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== +frames.js@^0.8.0: + version "0.8.5" + resolved "https://registry.yarnpkg.com/frames.js/-/frames.js-0.8.5.tgz#826ee2262508b5c87c601e1f1b6d8fb1176d1068" + integrity sha512-J6GASOb4CeTPv8YChKpH9yqzVOyccka8IWzusvrdYkyO88so/78LR0EqJwC04CYKwycaIo7JfpNmVIvO8HYf/A== + dependencies: + "@farcaster/core" "^0.14.7" + "@vercel/og" "^0.6.2" + cheerio "^1.0.0-rc.12" + protobufjs "^7.2.6" + viem "^2.7.1" + fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" @@ -7090,7 +7173,7 @@ ieee754@^1.2.1: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ignore@^5.0.5, ignore@^5.2.0, ignore@^5.2.4: +ignore@^5.0.5, ignore@^5.2.0, ignore@^5.2.4, ignore@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== @@ -9263,7 +9346,30 @@ neverthrow@^6.0.0: resolved "https://registry.yarnpkg.com/neverthrow/-/neverthrow-6.1.0.tgz#51a6e9ce2e06600045b3c1b37aecc536d267bf95" integrity sha512-xNbNjp/6M5vUV+mststgneJN9eJeJCDSYSBTaf3vxgvcKooP+8L0ATFpM8DGfmH7UWKJeoa24Qi33tBP9Ya3zA== -next@^14.0.4, next@^14.1.0, next@^14.1.3: +next@14.1.0: + version "14.1.0" + resolved "https://registry.yarnpkg.com/next/-/next-14.1.0.tgz#b31c0261ff9caa6b4a17c5af019ed77387174b69" + integrity sha512-wlzrsbfeSU48YQBjZhDzOwhWhGsy+uQycR8bHAOt1LY1bn3zZEcDyHQOEoN3aWzQ8LHCAJ1nqrWCc9XF2+O45Q== + dependencies: + "@next/env" "14.1.0" + "@swc/helpers" "0.5.2" + busboy "1.6.0" + caniuse-lite "^1.0.30001579" + graceful-fs "^4.2.11" + postcss "8.4.31" + styled-jsx "5.1.1" + optionalDependencies: + "@next/swc-darwin-arm64" "14.1.0" + "@next/swc-darwin-x64" "14.1.0" + "@next/swc-linux-arm64-gnu" "14.1.0" + "@next/swc-linux-arm64-musl" "14.1.0" + "@next/swc-linux-x64-gnu" "14.1.0" + "@next/swc-linux-x64-musl" "14.1.0" + "@next/swc-win32-arm64-msvc" "14.1.0" + "@next/swc-win32-ia32-msvc" "14.1.0" + "@next/swc-win32-x64-msvc" "14.1.0" + +next@^14.0.4, next@^14.1.0, next@^14.1.2, next@^14.1.3: version "14.1.4" resolved "https://registry.yarnpkg.com/next/-/next-14.1.4.tgz#203310f7310578563fd5c961f0db4729ce7a502d" integrity sha512-1WTaXeSrUwlz/XcnhGTY7+8eiaFvdet5z9u3V2jb+Ek1vFo0VhHKSAIJvDWfQpttWjnyw14kBeq28TPq7bTeEQ== @@ -12118,10 +12224,24 @@ viem@^1.0.0, viem@^1.1.4, viem@^1.12.2: isows "1.0.3" ws "8.13.0" +viem@^2.7.1: + version "2.9.0" + resolved "https://registry.yarnpkg.com/viem/-/viem-2.9.0.tgz#f59cd9b44d07ceaeacfd33477f116274860fd35d" + integrity sha512-7jNrY9GY4aLGU2qX4/TCXpA9qR4PDx5ctQyJpxoh8jDmlV0Rh2FLlnJsgJs9sAB8cKbNafkRTYQtuMA3OOn0JA== + dependencies: + "@adraffy/ens-normalize" "1.10.0" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@scure/bip32" "1.3.2" + "@scure/bip39" "1.2.1" + abitype "1.0.0" + isows "1.0.3" + ws "8.13.0" + viem@^2.7.12, viem@^2.7.14, viem@^2.7.8: - version "2.8.16" - resolved "https://registry.yarnpkg.com/viem/-/viem-2.8.16.tgz#30370390a6f109657b57c1a01b2793c4056b4e95" - integrity sha512-J8tu1aP7TfI2HT/IEmyJ+n+WInrA/cuMuJtfgvYhYgHBobxhYGc2SojHm5lZBWcWgErN1Ld7VcKUwTmPh4ToQA== + version "2.8.18" + resolved "https://registry.yarnpkg.com/viem/-/viem-2.8.18.tgz#ffb051bf80381ffefc98087a20c177b25463c9f4" + integrity sha512-Kq3kwkKziJ8rQeLkmdbSLheHDnA+tx2EdLKLmQ3N4FVtjKYjBP9tPL1r+fI6KltVUM1TDOhIHOdslDSp57VMMg== dependencies: "@adraffy/ens-normalize" "1.10.0" "@noble/curves" "1.2.0" @@ -12144,9 +12264,9 @@ vite-node@^1.2.0: vite "^5.0.0" vite@^5.0.0, vite@^5.0.11, vite@^5.0.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.2.tgz#b98f8de352d22e21d99508274ddd053ef82bf238" - integrity sha512-FWZbz0oSdLq5snUI0b6sULbz58iXFXdvkZfZWR/F0ZJuKTSPO7v72QPXt6KqYeMFb0yytNp6kZosxJ96Nr/wDQ== + version "5.2.3" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.3.tgz#198efc2fd4d80eac813b146a68a4b0dbde884fc2" + integrity sha512-+i1oagbvkVIhEy9TnEV+fgXsng13nZM90JQbrcPrf6DvW2mXARlz+DK7DLiDP+qeKoD1FCVx/1SpFL1CLq9Mhw== dependencies: esbuild "^0.20.1" postcss "^8.4.36" From c71817883616370c0415dd9354aaedcd993ff4f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kvasnic=CC=8Ca=CC=81k?= Date: Mon, 25 Mar 2024 15:45:07 +0100 Subject: [PATCH 11/42] feat: hono, express, remix templates --- examples/framesjs-starter/package.json | 6 +- package.json | 2 +- templates/express/.gitignore | 24 + templates/express/README.md | 11 + templates/express/index.html | 13 + templates/express/package.json | 35 + templates/express/server.js | 57 + templates/express/src/entry-server.tsx | 51 + templates/express/src/index.tsx | 0 templates/express/src/vite-env.d.ts | 1 + templates/express/tsconfig.json | 25 + templates/express/tsconfig.node.json | 11 + templates/express/vite.config.ts | 7 + templates/hono/.gitignore | 24 + templates/hono/README.md | 11 + templates/hono/index.html | 13 + templates/hono/package.json | 34 + templates/hono/src/index.tsx | 0 templates/hono/src/server.tsx | 67 + templates/hono/tsconfig.json | 25 + templates/hono/tsconfig.node.json | 11 + templates/hono/vite.config.ts | 13 + .../next-starter-with-examples/CHANGELOG.md | 153 -- .../next-starter-with-examples/app/debug.ts | 18 +- .../new-api-cache-control/frames/route.tsx | 28 + .../examples/new-api-cache-control/page.tsx | 33 + .../new-api-mint-button/frames/route.tsx | 76 + .../app/examples/new-api-mint-button/page.tsx | 33 + .../new-api-multi-page/frames/route.tsx | 47 + .../app/examples/new-api-multi-page/page.tsx | 33 + .../examples/new-api-multi-protocol/frames.ts | 34 + .../new-api-multi-protocol/frames/route.tsx | 20 + .../examples/new-api-multi-protocol/page.tsx | 33 + .../new-api-multi-protocol/who-am-i/route.tsx | 14 + .../frames/route.tsx | 65 + .../new-api-only-followers-can-mint/page.tsx | 33 + .../new-api-post-redirect/frames/route.tsx | 28 + .../examples/new-api-post-redirect/page.tsx | 33 + .../examples/new-api-slow-request/README.md | 6 + .../new-api-slow-request/frames/route.tsx | 126 + .../examples/new-api-slow-request/page.tsx | 33 + .../new-api-slow-request/slow-fetch/route.ts | 53 + .../new-api-slow-request/slow-fetch/types.ts | 15 + .../new-api-transaction/frames/route.tsx | 49 + .../app/examples/new-api-transaction/page.tsx | 33 + .../txdata/contracts/storage-registry.ts | 814 +++++++ .../new-api-transaction/txdata/route.ts | 58 + .../app/examples/new-api/frames/frames.ts | 5 + .../examples/new-api/frames/next/route.tsx | 21 + .../app/examples/new-api/frames/route.tsx | 24 + .../app/examples/new-api/page.tsx | 33 + .../only-followers-can-mint/frames/route.ts | 1 + .../examples/only-followers-can-mint/page.tsx | 115 + .../app/examples/page.tsx | 64 +- .../app/examples/transaction/page.tsx | 31 +- .../txdata/contracts/storage-registry.ts | 814 +++++++ .../app/examples/transaction/txdata/route.ts | 55 +- .../next-starter-with-examples/app/page.tsx | 4 + .../next-starter-with-examples/app/utils.ts | 12 +- .../next-starter-with-examples/package.json | 10 +- templates/next-utils-starter/CHANGELOG.md | 60 - .../next-utils-starter/app/api/frame/route.ts | 55 + .../app/api/frame/route.tsx | 46 - templates/next-utils-starter/app/layout.tsx | 46 +- templates/next-utils-starter/package.json | 7 +- templates/next/app/frames/route.tsx | 2 +- templates/next/package.json | 7 +- templates/remix/.gitignore | 5 + templates/remix/README.md | 36 + templates/remix/app/entry.client.tsx | 18 + templates/remix/app/entry.server.tsx | 140 ++ templates/remix/app/root.tsx | 29 + templates/remix/app/routes/_index.tsx | 40 + templates/remix/app/routes/frames._index.tsx | 55 + templates/remix/package.json | 36 + templates/remix/tsconfig.json | 32 + templates/remix/vite.config.ts | 10 + yarn.lock | 2165 +++++++++++++++-- 78 files changed, 5817 insertions(+), 470 deletions(-) create mode 100644 templates/express/.gitignore create mode 100644 templates/express/README.md create mode 100644 templates/express/index.html create mode 100644 templates/express/package.json create mode 100644 templates/express/server.js create mode 100644 templates/express/src/entry-server.tsx create mode 100644 templates/express/src/index.tsx create mode 100644 templates/express/src/vite-env.d.ts create mode 100644 templates/express/tsconfig.json create mode 100644 templates/express/tsconfig.node.json create mode 100644 templates/express/vite.config.ts create mode 100644 templates/hono/.gitignore create mode 100644 templates/hono/README.md create mode 100644 templates/hono/index.html create mode 100644 templates/hono/package.json create mode 100644 templates/hono/src/index.tsx create mode 100644 templates/hono/src/server.tsx create mode 100644 templates/hono/tsconfig.json create mode 100644 templates/hono/tsconfig.node.json create mode 100644 templates/hono/vite.config.ts delete mode 100644 templates/next-starter-with-examples/CHANGELOG.md create mode 100644 templates/next-starter-with-examples/app/examples/new-api-cache-control/frames/route.tsx create mode 100644 templates/next-starter-with-examples/app/examples/new-api-cache-control/page.tsx create mode 100644 templates/next-starter-with-examples/app/examples/new-api-mint-button/frames/route.tsx create mode 100644 templates/next-starter-with-examples/app/examples/new-api-mint-button/page.tsx create mode 100644 templates/next-starter-with-examples/app/examples/new-api-multi-page/frames/route.tsx create mode 100644 templates/next-starter-with-examples/app/examples/new-api-multi-page/page.tsx create mode 100644 templates/next-starter-with-examples/app/examples/new-api-multi-protocol/frames.ts create mode 100644 templates/next-starter-with-examples/app/examples/new-api-multi-protocol/frames/route.tsx create mode 100644 templates/next-starter-with-examples/app/examples/new-api-multi-protocol/page.tsx create mode 100644 templates/next-starter-with-examples/app/examples/new-api-multi-protocol/who-am-i/route.tsx create mode 100644 templates/next-starter-with-examples/app/examples/new-api-only-followers-can-mint/frames/route.tsx create mode 100644 templates/next-starter-with-examples/app/examples/new-api-only-followers-can-mint/page.tsx create mode 100644 templates/next-starter-with-examples/app/examples/new-api-post-redirect/frames/route.tsx create mode 100644 templates/next-starter-with-examples/app/examples/new-api-post-redirect/page.tsx create mode 100644 templates/next-starter-with-examples/app/examples/new-api-slow-request/README.md create mode 100644 templates/next-starter-with-examples/app/examples/new-api-slow-request/frames/route.tsx create mode 100644 templates/next-starter-with-examples/app/examples/new-api-slow-request/page.tsx create mode 100644 templates/next-starter-with-examples/app/examples/new-api-slow-request/slow-fetch/route.ts create mode 100644 templates/next-starter-with-examples/app/examples/new-api-slow-request/slow-fetch/types.ts create mode 100644 templates/next-starter-with-examples/app/examples/new-api-transaction/frames/route.tsx create mode 100644 templates/next-starter-with-examples/app/examples/new-api-transaction/page.tsx create mode 100644 templates/next-starter-with-examples/app/examples/new-api-transaction/txdata/contracts/storage-registry.ts create mode 100644 templates/next-starter-with-examples/app/examples/new-api-transaction/txdata/route.ts create mode 100644 templates/next-starter-with-examples/app/examples/new-api/frames/frames.ts create mode 100644 templates/next-starter-with-examples/app/examples/new-api/frames/next/route.tsx create mode 100644 templates/next-starter-with-examples/app/examples/new-api/frames/route.tsx create mode 100644 templates/next-starter-with-examples/app/examples/new-api/page.tsx create mode 100644 templates/next-starter-with-examples/app/examples/only-followers-can-mint/frames/route.ts create mode 100644 templates/next-starter-with-examples/app/examples/only-followers-can-mint/page.tsx create mode 100644 templates/next-starter-with-examples/app/examples/transaction/txdata/contracts/storage-registry.ts delete mode 100644 templates/next-utils-starter/CHANGELOG.md create mode 100644 templates/next-utils-starter/app/api/frame/route.ts delete mode 100644 templates/next-utils-starter/app/api/frame/route.tsx create mode 100644 templates/remix/.gitignore create mode 100644 templates/remix/README.md create mode 100644 templates/remix/app/entry.client.tsx create mode 100644 templates/remix/app/entry.server.tsx create mode 100644 templates/remix/app/root.tsx create mode 100644 templates/remix/app/routes/_index.tsx create mode 100644 templates/remix/app/routes/frames._index.tsx create mode 100644 templates/remix/package.json create mode 100644 templates/remix/tsconfig.json create mode 100644 templates/remix/vite.config.ts diff --git a/examples/framesjs-starter/package.json b/examples/framesjs-starter/package.json index b0a3b7491..ab28a3ce0 100644 --- a/examples/framesjs-starter/package.json +++ b/examples/framesjs-starter/package.json @@ -8,9 +8,7 @@ "dev:monorepo": "next dev", "build": "next build", "start": "next start", - "lint": "next lint", - "update-debugger": "npx degit github:framesjs/frames.js/examples/framesjs-starter/app/debug#main app/debug --force", - "update-framesjs": "yarn upgrade frames.js@latest && yarn run update-debugger" + "lint": "next lint" }, "dependencies": { "@farcaster/core": "^0.14.3", @@ -43,4 +41,4 @@ "tailwindcss": "^3.3.0", "typescript": "^5.3.3" } -} \ No newline at end of file +} diff --git a/package.json b/package.json index a906279e7..ce7b4f147 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "framesjs-monorepo", "private": true, "scripts": { - "build": "turbo build && node ./.scripts/prepare-create-frames.js", + "build": "turbo build --filter=!./templates/* && node ./.scripts/prepare-create-frames.js", "build:ci": "turbo build --filter=!debugger --filter=!framesjs-starter --filter=!utils-starter --filter=!docs", "dev": "FJS_MONOREPO=true turbo dev --filter=framesjs-starter... --filter=debugger...", "dev:custom-redirects": "turbo dev --filter=custom-redirects...", diff --git a/templates/express/.gitignore b/templates/express/.gitignore new file mode 100644 index 000000000..54f07af58 --- /dev/null +++ b/templates/express/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? \ No newline at end of file diff --git a/templates/express/README.md b/templates/express/README.md new file mode 100644 index 000000000..6837f6b7a --- /dev/null +++ b/templates/express/README.md @@ -0,0 +1,11 @@ +# Welcome to Express.js + Frames.js + +📖 See the [Express.js docs](https://expressjs.com) and [Frames.js docs](https://framesjs.org) for details on supported features. + +## Development + +Run the Frames.js debugger and Vite dev server: + +```shellscript +npm run dev +``` diff --git a/templates/express/index.html b/templates/express/index.html new file mode 100644 index 000000000..fca754be5 --- /dev/null +++ b/templates/express/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + Frames.js + Express.js + TS + + +
+ + + \ No newline at end of file diff --git a/templates/express/package.json b/templates/express/package.json new file mode 100644 index 000000000..22ee30bb6 --- /dev/null +++ b/templates/express/package.json @@ -0,0 +1,35 @@ +{ + "name": "template-express", + "version": "0.0.0", + "type": "module", + "private": true, + "dependencies": { + "compression": "^1.7.4", + "express": "^4.19.1", + "frames.js": "^0.9.6", + "react": "^18.2.0", + "sirv": "^2.0.4" + }, + "devDependencies": { + "@frames.js/debugger": "^0.1.9", + "@types/express": "^4.17.21", + "@types/node": "^18.17.0", + "@types/react": "^18.2.45", + "@vitejs/plugin-react": "^4.2.1", + "concurrently": "^8.2.2", + "cross-env": "^7.0.3", + "typescript": "^5.1.6", + "vite": "^5.1.0", + "vite-tsconfig-paths": "^4.2.1" + }, + "engines": { + "node": ">=18.17.0" + }, + "scripts": { + "dev": "concurrently --kill-others \"node server\" \"frames --url http://localhost:5173\"", + "build": "npm run build:client && npm run build:server", + "build:client": "vite build --ssrManifest --outDir dist/client", + "build:server": "vite build --ssr src/entry-server.tsx --outDir dist/server", + "preview": "cross-env NODE_ENV=production node server" + } +} diff --git a/templates/express/server.js b/templates/express/server.js new file mode 100644 index 000000000..f83570458 --- /dev/null +++ b/templates/express/server.js @@ -0,0 +1,57 @@ +import express from "express"; + +// Constants +const isProduction = process.env.NODE_ENV === "production"; +const port = process.env.PORT || 5173; +const base = process.env.BASE || "/"; + +// Create http server +const app = express(); + +// Add Vite or respective production middlewares +let vite; +if (!isProduction) { + const { createServer } = await import("vite"); + vite = await createServer({ + server: { middlewareMode: true }, + appType: "custom", + base, + }); + app.use(vite.middlewares); +} else { + const compression = (await import("compression")).default; + const sirv = (await import("sirv")).default; + app.use(compression()); + app.use(base, sirv("./dist/client", { extensions: [] })); +} + +// Serve HTML +app.use("*", async (req, res) => { + try { + const url = req.originalUrl.replace(base, ""); + + /** + * @type {import('express').Handler} + */ + let handleRequest; + if (!isProduction) { + // Always read fresh template in development + handleRequest = (await vite.ssrLoadModule("/src/entry-server.tsx")) + .handleRequest; + } else { + handleRequest = (await import("./dist/server/entry-server.js")) + .handleRequest; + } + + handleRequest(req, res); + } catch (e) { + vite?.ssrFixStacktrace(e); + console.log(e.stack); + res.status(500).end(e.stack); + } +}); + +// Start http server +app.listen(port, () => { + console.log(`Server started at http://localhost:${port}`); +}); diff --git a/templates/express/src/entry-server.tsx b/templates/express/src/entry-server.tsx new file mode 100644 index 000000000..fe5e89b6d --- /dev/null +++ b/templates/express/src/entry-server.tsx @@ -0,0 +1,51 @@ +import { farcasterHubContext } from "frames.js/middleware"; +import { createFrames, Button } from 'frames.js/express'; + +const frames = createFrames({ + middleware: [ + farcasterHubContext({ + // remove if you aren't using @frames.js/debugger or you just don't want to use the debugger hub + ...(process.env.NODE_ENV === "production" + ? {} + : { + hubHttpUrl: "http://localhost:3010/hub", + }), + }), + ], +}); + +export const handleRequest = frames(async ctx => { + return { + image: ctx.message ? ( +
+ GM, {ctx.message.requesterUserData?.displayName}! Your FID is{" "} + {ctx.message.requesterFid} + {", "} + {ctx.message.requesterFid < 20_000 + ? "you're OG!" + : "welcome to the Farcaster!"} +
+ ) : ( +
+ Say GM +
+ ), + buttons: !ctx.url.searchParams.has("saidGm") + ? [ + , + ] + : [], + }; +}); \ No newline at end of file diff --git a/templates/express/src/index.tsx b/templates/express/src/index.tsx new file mode 100644 index 000000000..e69de29bb diff --git a/templates/express/src/vite-env.d.ts b/templates/express/src/vite-env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/templates/express/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/templates/express/tsconfig.json b/templates/express/tsconfig.json new file mode 100644 index 000000000..97cbe737d --- /dev/null +++ b/templates/express/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "Bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/templates/express/tsconfig.node.json b/templates/express/tsconfig.node.json new file mode 100644 index 000000000..1974ea683 --- /dev/null +++ b/templates/express/tsconfig.node.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "allowSyntheticDefaultImports": true, + "jsx": "preserve" + }, + "include": ["vite.config.ts"] +} diff --git a/templates/express/vite.config.ts b/templates/express/vite.config.ts new file mode 100644 index 000000000..9cc50ead1 --- /dev/null +++ b/templates/express/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +}); diff --git a/templates/hono/.gitignore b/templates/hono/.gitignore new file mode 100644 index 000000000..54f07af58 --- /dev/null +++ b/templates/hono/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? \ No newline at end of file diff --git a/templates/hono/README.md b/templates/hono/README.md new file mode 100644 index 000000000..25a312857 --- /dev/null +++ b/templates/hono/README.md @@ -0,0 +1,11 @@ +# Welcome to Hono + Frames.js + +📖 See the [Hono docs](https://hono.dev) and [Frames.js docs](https://framesjs.org) for details on supported features. + +## Development + +Run the Frames.js debugger and Vite dev server: + +```shellscript +npm run dev +``` diff --git a/templates/hono/index.html b/templates/hono/index.html new file mode 100644 index 000000000..e7c576e55 --- /dev/null +++ b/templates/hono/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + Frames.js + Hono + TS + + +
+ + + \ No newline at end of file diff --git a/templates/hono/package.json b/templates/hono/package.json new file mode 100644 index 000000000..564262d24 --- /dev/null +++ b/templates/hono/package.json @@ -0,0 +1,34 @@ +{ + "name": "template-hono", + "version": "0.0.0", + "type": "module", + "private": true, + "dependencies": { + "@hono/node-server": "^1.9.0", + "hono": "^4.1.3", + "frames.js": "^0.9.6", + "react": "^18.2.0" + }, + "devDependencies": { + "@frames.js/debugger": "^0.1.9", + "@hono/vite-dev-server": "^0.10.0", + "@types/node": "^18.17.0", + "@types/react": "^18.2.45", + "@vitejs/plugin-react": "^4.2.1", + "concurrently": "^8.2.2", + "cross-env": "^7.0.3", + "typescript": "^5.1.6", + "vite": "^5.1.0", + "vite-tsconfig-paths": "^4.2.1" + }, + "engines": { + "node": ">=18.17.0" + }, + "scripts": { + "dev": "concurrently --kill-others \"vite\" \"frames --url http://localhost:5173\"", + "build": "npm run build:client && npm run build:server", + "build:client": "vite build --ssrManifest --outDir dist/client", + "build:server": "vite build --ssr src/server.tsx --outDir dist/server", + "preview": "cross-env-shell NODE_ENV=production \"npm run build && node dist/server/server.js\"" + } +} diff --git a/templates/hono/src/index.tsx b/templates/hono/src/index.tsx new file mode 100644 index 000000000..e69de29bb diff --git a/templates/hono/src/server.tsx b/templates/hono/src/server.tsx new file mode 100644 index 000000000..4a4d094b0 --- /dev/null +++ b/templates/hono/src/server.tsx @@ -0,0 +1,67 @@ +import { farcasterHubContext } from "frames.js/middleware"; +import { createFrames, Button } from 'frames.js/hono'; +import { Hono } from 'hono'; +import { serve } from "@hono/node-server"; + +const app = new Hono(); + +const frames = createFrames({ + middleware: [ + farcasterHubContext({ + // remove if you aren't using @frames.js/debugger or you just don't want to use the debugger hub + ...(process.env.NODE_ENV === "production" + ? {} + : { + hubHttpUrl: "http://localhost:3010/hub", + }), + }), + ], +}); + +const handleRequest = frames(async ctx => { + return { + image: ctx.message ? ( +
+ GM, {ctx.message.requesterUserData?.displayName}! Your FID is{" "} + {ctx.message.requesterFid} + {", "} + {ctx.message.requesterFid < 20_000 + ? "you're OG!" + : "welcome to the Farcaster!"} +
+ ) : ( +
+ Say GM +
+ ), + buttons: !ctx.url.searchParams.has("saidGm") + ? [ + , + ] + : [], + }; +}); + +app.get('/', handleRequest); +app.post('/', handleRequest); + +// expose app for `@hono/vite-dev-server` +export default app; + +if (process.env.NODE_ENV === 'production') { + serve({ ...app, port: 3000 }, info => { + console.log(`Server running on http://localhost:${info.port}`); + }) +} \ No newline at end of file diff --git a/templates/hono/tsconfig.json b/templates/hono/tsconfig.json new file mode 100644 index 000000000..97cbe737d --- /dev/null +++ b/templates/hono/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "Bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/templates/hono/tsconfig.node.json b/templates/hono/tsconfig.node.json new file mode 100644 index 000000000..1974ea683 --- /dev/null +++ b/templates/hono/tsconfig.node.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "allowSyntheticDefaultImports": true, + "jsx": "preserve" + }, + "include": ["vite.config.ts"] +} diff --git a/templates/hono/vite.config.ts b/templates/hono/vite.config.ts new file mode 100644 index 000000000..33520be12 --- /dev/null +++ b/templates/hono/vite.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; +import devServer from "@hono/vite-dev-server"; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + react(), + devServer({ + entry: "./src/server.tsx", + }), + ], +}); diff --git a/templates/next-starter-with-examples/CHANGELOG.md b/templates/next-starter-with-examples/CHANGELOG.md deleted file mode 100644 index 3d9d43772..000000000 --- a/templates/next-starter-with-examples/CHANGELOG.md +++ /dev/null @@ -1,153 +0,0 @@ -# framesjs-starter - -## 0.2.2 - -### Patch Changes - -- 72e6617: feat: tx support -- Updated dependencies [72e6617] -- Updated dependencies [7ccc562] - - frames.js@0.8.0 - -## 0.2.1 - -### Patch Changes - -- Updated dependencies [01fc5fe] -- Updated dependencies [60c6e56] -- Updated dependencies [e335829] -- Updated dependencies [eee74a9] - - frames.js@0.7.0 - -## 0.2.0 - -### Minor Changes - -- 845b30c: refactor: make frame validation errors arbitraty, remove unnecessary validateFrame function - -### Patch Changes - -- Updated dependencies [845b30c] -- Updated dependencies [ce1cec6] -- Updated dependencies [845b30c] - - frames.js@0.6.0 - -## 0.1.12 - -### Patch Changes - -- 99b998f: fix: debugger build -- 108280c: feat: add mock hub state to debugger -- 1707ea4: feat: `DEBUG_HUB_HTTP_URL` env var -- Updated dependencies [18c887d] -- Updated dependencies [0ba4b88] -- Updated dependencies [f9d4356] - - frames.js@0.5.2 - -## 0.1.11 - -### Patch Changes - -- 157ec44: chore: update fallback neynar hub api url -- 548a9c3: feat: multi-page example -- 426d5eb: feat: validate frame image data uri length in debugger -- 8317894: fix: reset input state on submit, waiting state buttons styling -- Updated dependencies [157ec44] -- Updated dependencies [426d5eb] -- Updated dependencies [70a0ff6] -- Updated dependencies [d1596ac] -- Updated dependencies [62be50d] - - frames.js@0.5.1 - -## 0.1.10 - -### Patch Changes - -- Updated dependencies [40d2662] - - frames.js@0.5.0 - -## 0.1.9 - -### Patch Changes - -- d861fb9: fix: url validation and smoother navigation -- Updated dependencies [e54b9ad] -- Updated dependencies [a09c555] - - frames.js@0.4.3 - -## 0.1.8 - -### Patch Changes - -- 2150e11: chore(debugger): remove mint spec warning -- Updated dependencies [ccb8317] - - frames.js@0.4.2 - -## 0.1.7 - -### Patch Changes - -- 8112f6f: fix: use neynar hubs as fallback -- Updated dependencies [800d887] -- Updated dependencies [8112f6f] -- Updated dependencies [fd70614] -- Updated dependencies [b71f05b] -- Updated dependencies [8112f6f] - - frames.js@0.4.1 - -## 0.1.6 - -### Patch Changes - -- ccd3302: feat: JSX-based frame image rendering -- Updated dependencies [ccd3302] - - frames.js@0.4.0 - -## 0.1.5 - -### Patch Changes - -- 03d041e: feat: mint action -- Updated dependencies [03d041e] - - frames.js@0.3.0 - -## 0.1.4 - -### Patch Changes - -- 3ed2cef: fix: generate correct image data in `generateImage` example -- Updated dependencies [0d9cfaf] - - frames.js@0.2.1 - -## 0.1.3 - -### Patch Changes - -- Updated dependencies [608bac9] - - frames.js@0.2.0 - -## 0.1.2 - -### Patch Changes - -- 40d0ad7: feat: Add `getFrameMessage`, which parse frame action payloads and optionally fetches additional context from hubs. - - feat(debugger): Forward unmocked hub requests to an actual hub. - -- Updated dependencies [40d0ad7] -- Updated dependencies [57649be] -- Updated dependencies [518ada3] - - frames.js@0.1.1 - -## 0.1.1 - -### Patch Changes - -- 05af691: feat: adds an option to impersonate an FID as an alternative to creating a new onchain signer -- fb3cfaa: fix(debug): untrusted data url now uses original frame url -- 99536fb: fix: frame action message creation to not include inputText if inputText was not requested by the frame -- Updated dependencies [1a73918] -- Updated dependencies [99536fb] -- Updated dependencies [501861d] -- Updated dependencies [1598cb6] - - frames.js@0.1.0 diff --git a/templates/next-starter-with-examples/app/debug.ts b/templates/next-starter-with-examples/app/debug.ts index 54aa6916d..d91a3acec 100644 --- a/templates/next-starter-with-examples/app/debug.ts +++ b/templates/next-starter-with-examples/app/debug.ts @@ -1,15 +1,19 @@ const DEFAULT_DEBUGGER_URL = process.env.DEBUGGER_URL ?? "http://localhost:3010/"; -export const DEFAULT_DEBUGGER_HUB_URL = new URL( - "/hub", - DEFAULT_DEBUGGER_URL -).toString(); +export const DEFAULT_DEBUGGER_HUB_URL = + process.env.NODE_ENV === "development" + ? new URL("/hub", DEFAULT_DEBUGGER_URL).toString() + : undefined; export function createDebugUrl(frameURL: string | URL): string { - const url = new URL("/", DEFAULT_DEBUGGER_URL); + try { + const url = new URL("/", DEFAULT_DEBUGGER_URL); - url.searchParams.set("url", frameURL.toString()); + url.searchParams.set("url", frameURL.toString()); - return url.toString(); + return url.toString(); + } catch (error) { + return "#"; + } } diff --git a/templates/next-starter-with-examples/app/examples/new-api-cache-control/frames/route.tsx b/templates/next-starter-with-examples/app/examples/new-api-cache-control/frames/route.tsx new file mode 100644 index 000000000..ee6293fa3 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-cache-control/frames/route.tsx @@ -0,0 +1,28 @@ +/* eslint-disable react/jsx-key */ +import { Button } from "frames.js/next"; +import { createFrames } from "frames.js/next"; + +const frames = createFrames({ + basePath: "/examples/new-api-cache-control", +}); + +const handleRequest = frames(async (ctx) => { + return { + image: ( +
+ The current time is {new Date().toLocaleString()} +
+ ), + imageOptions: { + aspectRatio: "1:1", + }, + buttons: [], + headers: { + // Max cache age in seconds + "Cache-Control": "max-age=5", + }, + }; +}); + +export const GET = handleRequest; +export const POST = handleRequest; diff --git a/templates/next-starter-with-examples/app/examples/new-api-cache-control/page.tsx b/templates/next-starter-with-examples/app/examples/new-api-cache-control/page.tsx new file mode 100644 index 000000000..e0053b7b0 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-cache-control/page.tsx @@ -0,0 +1,33 @@ +import Link from "next/link"; +import { currentURL, vercelURL } from "../../utils"; +import { createDebugUrl } from "../../debug"; +import type { Metadata } from "next"; +import { fetchMetadata } from "frames.js/next"; + +export async function generateMetadata(): Promise { + return { + title: "New api example", + description: "This is a new api example", + other: { + ...(await fetchMetadata( + new URL( + "/examples/new-api-cache-control/frames", + vercelURL() || "http://localhost:3000" + ) + )), + }, + }; +} + +export default async function Home() { + const url = currentURL("/examples/new-api-cache-control"); + + return ( +
+ Cache control example{" "} + + Debug + +
+ ); +} diff --git a/templates/next-starter-with-examples/app/examples/new-api-mint-button/frames/route.tsx b/templates/next-starter-with-examples/app/examples/new-api-mint-button/frames/route.tsx new file mode 100644 index 000000000..23ee9ccf8 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-mint-button/frames/route.tsx @@ -0,0 +1,76 @@ +/* eslint-disable react/jsx-key */ +import { Button, createFrames } from "frames.js/next"; +import { getTokenUrl } from "frames.js"; +import { zora } from "viem/chains"; + +const nfts: { + src: string; + tokenUrl: string; +}[] = [ + { + src: "https://ipfs.decentralized-content.com/ipfs/bafybeifs7vasy5zbmnpixt7tb6efi35kcrmpoz53d3vg5pwjz52q7fl6pq/cook.png", + tokenUrl: getTokenUrl({ + address: "0x99de131ff1223c4f47316c0bb50e42f356dafdaa", + chain: zora, + tokenId: "2", + }), + }, + { + src: "https://remote-image.decentralized-content.com/image?url=https%3A%2F%2Fipfs.decentralized-content.com%2Fipfs%2Fbafybeiegrnialwu66u3nwzkn4gik4i2x2h4ip7y3w2dlymzlpxb5lrqbom&w=1920&q=75", + tokenUrl: getTokenUrl({ + address: "0x060f3edd18c47f59bd23d063bbeb9aa4a8fec6df", + chain: zora, + tokenId: "1", + }), + }, + { + src: "https://remote-image.decentralized-content.com/image?url=https%3A%2F%2Fipfs.decentralized-content.com%2Fipfs%2Fbafybeidc6e5t3qmyckqh4fr2ewrov5asmeuv4djycopvo3ro366nd3bfpu&w=1920&q=75", + tokenUrl: getTokenUrl({ + address: "0x8f5ed2503b71e8492badd21d5aaef75d65ac0042", + chain: zora, + tokenId: "3", + }), + }, +]; + +const frames = createFrames({ + basePath: "/examples/new-api-mint-button/frames", +}); + +const handleRequest = frames(async (ctx) => { + const page = Number(ctx.searchParams?.pageIndex ?? 0); + return { + image: nfts[page]!.src, + imageOptions: { + aspectRatio: "1:1", + }, + buttons: [ + , + , + , + ], + }; +}); + +export const GET = handleRequest; +export const POST = handleRequest; diff --git a/templates/next-starter-with-examples/app/examples/new-api-mint-button/page.tsx b/templates/next-starter-with-examples/app/examples/new-api-mint-button/page.tsx new file mode 100644 index 000000000..7ab663d32 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-mint-button/page.tsx @@ -0,0 +1,33 @@ +import Link from "next/link"; +import { currentURL, vercelURL } from "../../utils"; +import { createDebugUrl } from "../../debug"; +import type { Metadata } from "next"; +import { fetchMetadata } from "frames.js/next"; + +export async function generateMetadata(): Promise { + return { + title: "New api example", + description: "This is a new api example", + other: { + ...(await fetchMetadata( + new URL( + "/examples/new-api-mint-button/frames", + vercelURL() || "http://localhost:3000" + ) + )), + }, + }; +} + +export default async function Home() { + const url = currentURL("/examples/new-api-mint-button"); + + return ( +
+ New api mint button example.{" "} + + Debug + +
+ ); +} diff --git a/templates/next-starter-with-examples/app/examples/new-api-multi-page/frames/route.tsx b/templates/next-starter-with-examples/app/examples/new-api-multi-page/frames/route.tsx new file mode 100644 index 000000000..8973e65f0 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-multi-page/frames/route.tsx @@ -0,0 +1,47 @@ +/* eslint-disable react/jsx-key */ +import { createFrames, Button } from "frames.js/next"; + +const totalPages = 5; + +const frames = createFrames({ + basePath: "/examples/new-api-multi-page/frames", +}); + +const handleRequest = frames(async (ctx) => { + const pageIndex = Number(ctx.searchParams.pageIndex || 0); + + const imageUrl = `https://picsum.photos/seed/frames.js-${pageIndex}/300/200`; + + return { + image: ( +
+ Image +
+ This is slide {pageIndex + 1} / {totalPages} +
+
+ ), + buttons: [ + , + , + ], + textInput: "Type something!", + }; +}); + +export const GET = handleRequest; +export const POST = handleRequest; diff --git a/templates/next-starter-with-examples/app/examples/new-api-multi-page/page.tsx b/templates/next-starter-with-examples/app/examples/new-api-multi-page/page.tsx new file mode 100644 index 000000000..7c92dee31 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-multi-page/page.tsx @@ -0,0 +1,33 @@ +import Link from "next/link"; +import { currentURL, vercelURL } from "../../utils"; +import { createDebugUrl } from "../../debug"; +import type { Metadata } from "next"; +import { fetchMetadata } from "frames.js/next"; + +export async function generateMetadata(): Promise { + return { + title: "New api example", + description: "This is a new api example", + other: { + ...(await fetchMetadata( + new URL( + "/examples/new-api-multi-page/frames", + vercelURL() || "http://localhost:3000" + ) + )), + }, + }; +} + +export default async function Home() { + const url = currentURL("/examples/new-api-multi-page"); + + return ( +
+ Multi-page example + + Debug + +
+ ); +} diff --git a/templates/next-starter-with-examples/app/examples/new-api-multi-protocol/frames.ts b/templates/next-starter-with-examples/app/examples/new-api-multi-protocol/frames.ts new file mode 100644 index 000000000..0234c8657 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-multi-protocol/frames.ts @@ -0,0 +1,34 @@ +/* eslint-disable react/jsx-key */ +import { farcasterHubContext, openframes } from "frames.js/middleware"; +import { createFrames } from "frames.js/next"; +import { getXmtpFrameMessage, isXmtpFrameActionPayload } from "frames.js/xmtp"; +import { DEFAULT_DEBUGGER_HUB_URL } from "../../debug"; + +export const frames = createFrames({ + basePath: "/examples/new-api-multi-protocol", + initialState: { + pageIndex: 0, + }, + middleware: [ + farcasterHubContext({ + hubHttpUrl: DEFAULT_DEBUGGER_HUB_URL, + }), + openframes({ + clientProtocol: { + id: "xmtp", + version: "2024-02-09", + }, + handler: { + isValidPayload: (body: JSON) => isXmtpFrameActionPayload(body), + getFrameMessage: async (body: JSON) => { + if (!isXmtpFrameActionPayload(body)) { + return undefined; + } + const result = await getXmtpFrameMessage(body); + + return { ...result }; + }, + }, + }), + ], +}); diff --git a/templates/next-starter-with-examples/app/examples/new-api-multi-protocol/frames/route.tsx b/templates/next-starter-with-examples/app/examples/new-api-multi-protocol/frames/route.tsx new file mode 100644 index 000000000..07043b99d --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-multi-protocol/frames/route.tsx @@ -0,0 +1,20 @@ +import { Button } from "frames.js/next"; +import { frames } from "../frames"; + +const handleRequest = frames(async (ctx) => { + return { + image: ( +
+
Click the button
+
+ ), + buttons: [ + , + ], + }; +}); + +export const GET = handleRequest; +export const POST = handleRequest; diff --git a/templates/next-starter-with-examples/app/examples/new-api-multi-protocol/page.tsx b/templates/next-starter-with-examples/app/examples/new-api-multi-protocol/page.tsx new file mode 100644 index 000000000..4051f3eb4 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-multi-protocol/page.tsx @@ -0,0 +1,33 @@ +import Link from "next/link"; +import { currentURL, vercelURL } from "../../utils"; +import { createDebugUrl } from "../../debug"; +import type { Metadata } from "next"; +import { fetchMetadata } from "frames.js/next"; + +export async function generateMetadata(): Promise { + return { + title: "New api example", + description: "This is a new api example", + other: { + ...(await fetchMetadata( + new URL( + "/examples/new-api-multi-protocol/frames", + vercelURL() || "http://localhost:3000" + ) + )), + }, + }; +} + +export default async function Home() { + const url = currentURL("/examples/new-api-multi-protocol"); + + return ( +
+ Multi-protocol example + + Debug + +
+ ); +} diff --git a/templates/next-starter-with-examples/app/examples/new-api-multi-protocol/who-am-i/route.tsx b/templates/next-starter-with-examples/app/examples/new-api-multi-protocol/who-am-i/route.tsx new file mode 100644 index 000000000..ca633b088 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-multi-protocol/who-am-i/route.tsx @@ -0,0 +1,14 @@ +import { frames } from "../frames"; + +export const POST = frames(async (ctx) => { + return { + image: ( +
+ You are{" "} + {ctx.message?.requesterCustodyAddress || + ctx.message?.verifiedWalletAddress}{" "} + from {ctx.clientProtocol?.id} +
+ ), + }; +}); diff --git a/templates/next-starter-with-examples/app/examples/new-api-only-followers-can-mint/frames/route.tsx b/templates/next-starter-with-examples/app/examples/new-api-only-followers-can-mint/frames/route.tsx new file mode 100644 index 000000000..31cc4f6a5 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-only-followers-can-mint/frames/route.tsx @@ -0,0 +1,65 @@ +/* eslint-disable react/jsx-key */ +import { getTokenUrl } from "frames.js"; +import { farcasterHubContext } from "frames.js/middleware"; +import { Button, createFrames } from "frames.js/next"; +import { zora } from "viem/chains"; +import { DEFAULT_DEBUGGER_HUB_URL } from "../../../debug"; + +const frames = createFrames({ + basePath: "/examples/new-api-only-followers-can-mint/frames", + middleware: [ + farcasterHubContext({ + hubHttpUrl: DEFAULT_DEBUGGER_HUB_URL, + }), + ], +}); + +const handleRequest = frames(async (ctx) => { + const page = ctx.searchParams?.page ?? "initial"; + if (page === "initial") + return { + image: ( + +
+ You can mint if you follow the caster. +
+
+ ), + buttons: [ + , + ], + }; + return { + image: ( +
+ {ctx.message?.requesterFollowsCaster + ? "You are following the caster." + : "You are not following the caster"} +
+ ), + buttons: [ + ctx.message?.requesterFollowsCaster ? ( + + ) : ( + + ), + ], + }; +}); + +export const GET = handleRequest; +export const POST = handleRequest; diff --git a/templates/next-starter-with-examples/app/examples/new-api-only-followers-can-mint/page.tsx b/templates/next-starter-with-examples/app/examples/new-api-only-followers-can-mint/page.tsx new file mode 100644 index 000000000..411c881cb --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-only-followers-can-mint/page.tsx @@ -0,0 +1,33 @@ +import Link from "next/link"; +import { currentURL, vercelURL } from "../../utils"; +import { createDebugUrl } from "../../debug"; +import type { Metadata } from "next"; +import { fetchMetadata } from "frames.js/next"; + +export async function generateMetadata(): Promise { + return { + title: "New api example", + description: "This is a new api example", + other: { + ...(await fetchMetadata( + new URL( + "/examples/new-api-only-followers-can-mint/frames", + vercelURL() || "http://localhost:3000" + ) + )), + }, + }; +} + +export default async function Home() { + const url = currentURL("/examples/new-api-only-followers-can-mint"); + + return ( +
+ New api example only followers can mint.{" "} + + Debug + +
+ ); +} diff --git a/templates/next-starter-with-examples/app/examples/new-api-post-redirect/frames/route.tsx b/templates/next-starter-with-examples/app/examples/new-api-post-redirect/frames/route.tsx new file mode 100644 index 000000000..b478f04b1 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-post-redirect/frames/route.tsx @@ -0,0 +1,28 @@ +/* eslint-disable react/jsx-key */ +import { createFrames, Button } from "frames.js/next"; +import { redirect } from "frames.js/core"; + +const frames = createFrames({ + basePath: "/examples/new-api-post-redirect/frames", +}); + +const handleRequest = frames(async (ctx) => { + if (ctx.pressedButton?.action === "post_redirect") { + // Do something with the POST + + // when post_redirect button is clicked you must return a redirect response + return redirect("https://google.com"); + } + + return { + image: ( +
+
Post redirect example
+
+ ), + buttons: [], + }; +}); + +export const GET = handleRequest; +export const POST = handleRequest; diff --git a/templates/next-starter-with-examples/app/examples/new-api-post-redirect/page.tsx b/templates/next-starter-with-examples/app/examples/new-api-post-redirect/page.tsx new file mode 100644 index 000000000..ac5b9b54c --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-post-redirect/page.tsx @@ -0,0 +1,33 @@ +import Link from "next/link"; +import { currentURL, vercelURL } from "../../utils"; +import { createDebugUrl } from "../../debug"; +import type { Metadata } from "next"; +import { fetchMetadata } from "frames.js/next"; + +export async function generateMetadata(): Promise { + return { + title: "New api example", + description: "This is a new api example", + other: { + ...(await fetchMetadata( + new URL( + "/examples/new-api-post-redirect/frames", + vercelURL() || "http://localhost:3000" + ) + )), + }, + }; +} + +export default async function Home() { + const url = currentURL("/examples/new-api-post-redirect"); + + return ( +
+ Post redirect example + + Debug + +
+ ); +} diff --git a/templates/next-starter-with-examples/app/examples/new-api-slow-request/README.md b/templates/next-starter-with-examples/app/examples/new-api-slow-request/README.md new file mode 100644 index 000000000..0f563d1d5 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-slow-request/README.md @@ -0,0 +1,6 @@ +# Step 1 + +Setup a key value store +https://vercel.com/docs/storage/vercel-kv/quickstart + +or follow the steps in this PR to set it up locally using Docker: https://github.com/vercel/storage/issues/281#issuecomment-1650439329 diff --git a/templates/next-starter-with-examples/app/examples/new-api-slow-request/frames/route.tsx b/templates/next-starter-with-examples/app/examples/new-api-slow-request/frames/route.tsx new file mode 100644 index 000000000..a9944f032 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-slow-request/frames/route.tsx @@ -0,0 +1,126 @@ +import { kv } from "@vercel/kv"; +import { types } from "frames.js/core"; +import { createFrames, Button } from "frames.js/next"; +import { RandomNumberRequestStateValue } from "../slow-fetch/types"; + +const frames = createFrames({ + basePath: "/examples/new-api-slow-request/frames", +}); + +const handleRequest = frames(async (ctx) => { + const initialFrame = { + image: ( +
+ This random number generator takes 10 seconds to respond +
+ ), + buttons: [ + , + ], + } satisfies types.FrameDefinition; + + const checkStatusFrame = { + image: ( +
+ Loading... +
+ ), + buttons: [ + , + ], + } satisfies types.FrameDefinition; + + if (!ctx.message) { + return initialFrame; + } + + const { requesterFid } = ctx.message; + const uniqueId = `fid:${requesterFid}`; + + const existingRequest = await kv.get(uniqueId); + + if (existingRequest) { + switch (existingRequest.status) { + case "pending": + return checkStatusFrame; + case "success": { + if (ctx.url.searchParams.get("reset") === "true") { + // reset to initial state + await kv.del(uniqueId); + } + + return { + image: ( +
+ The number is {existingRequest.data} +
+ ), + buttons: [ + , + ], + } satisfies types.FrameDefinition; + } + case "error": { + if (ctx.url.searchParams.get("retry") === "true") { + // reset to initial state + await kv.del(uniqueId); + + return initialFrame; + } else { + return { + image: {existingRequest.error}, + buttons: [ + , + ], + } satisfies types.FrameDefinition; + } + } + } + } else { + await kv.set( + uniqueId, + { + status: "pending", + timestamp: new Date().getTime(), + }, + // set as pending for one minute + { ex: 60 } + ); + + // start request, don't await it! Return a loading page, let this run in the background + fetch( + new URL( + "/examples/new-api-slow-request/slow-fetch", + process.env.NEXT_PUBLIC_HOST + ).toString(), + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(await ctx.request.clone().json()), + } + ); + } + + return initialFrame; +}); + +export const GET = handleRequest; +export const POST = handleRequest; diff --git a/templates/next-starter-with-examples/app/examples/new-api-slow-request/page.tsx b/templates/next-starter-with-examples/app/examples/new-api-slow-request/page.tsx new file mode 100644 index 000000000..40022d793 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-slow-request/page.tsx @@ -0,0 +1,33 @@ +import Link from "next/link"; +import { currentURL, vercelURL } from "../../utils"; +import { createDebugUrl } from "../../debug"; +import type { Metadata } from "next"; +import { fetchMetadata } from "frames.js/next"; + +export async function generateMetadata(): Promise { + return { + title: "New api example", + description: "This is a new api example", + other: { + ...(await fetchMetadata( + new URL( + "/examples/new-api-slow-request/frames", + vercelURL() || "http://localhost:3000" + ) + )), + }, + }; +} + +export default async function Home() { + const url = currentURL("/examples/new-api-slow-request"); + + return ( +
+ Slow request example + + Debug + +
+ ); +} diff --git a/templates/next-starter-with-examples/app/examples/new-api-slow-request/slow-fetch/route.ts b/templates/next-starter-with-examples/app/examples/new-api-slow-request/slow-fetch/route.ts new file mode 100644 index 000000000..138b20a98 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-slow-request/slow-fetch/route.ts @@ -0,0 +1,53 @@ +import { getFrameMessage } from "frames.js"; +import { NextRequest, NextResponse } from "next/server"; +import { kv } from "@vercel/kv"; +import { RandomNumberRequestStateValue } from "./types"; +import { DEFAULT_DEBUGGER_HUB_URL } from "../../../debug"; + +const MAXIMUM_KV_RESULT_LIFETIME_IN_SECONDS = 2 * 60; // 2 minutes + +export async function POST(req: NextRequest) { + const body = await req.json(); + + // verify independently + const frameMessage = await getFrameMessage(body, { + hubHttpUrl: DEFAULT_DEBUGGER_HUB_URL, + }); + + const uniqueId = `fid:${frameMessage.requesterFid}`; + + // Wait 10 seconds + await new Promise((resolve) => setTimeout(resolve, 10000)); + + try { + const randomNumber = Math.random(); + + await kv.set( + uniqueId, + { + data: randomNumber, + status: "success", + timestamp: new Date().getTime(), + }, + { ex: MAXIMUM_KV_RESULT_LIFETIME_IN_SECONDS } + ); + + return NextResponse.json({ + data: randomNumber, + status: "success", + timestamp: new Date().getTime(), + }); + } catch (e) { + await kv.set( + uniqueId, + { + error: String(e), + status: "error", + timestamp: new Date().getTime(), + }, + { ex: MAXIMUM_KV_RESULT_LIFETIME_IN_SECONDS } + ); + // Handle errors + return NextResponse.json({ message: e }, { status: 500 }); + } +} diff --git a/templates/next-starter-with-examples/app/examples/new-api-slow-request/slow-fetch/types.ts b/templates/next-starter-with-examples/app/examples/new-api-slow-request/slow-fetch/types.ts new file mode 100644 index 000000000..72fa08eeb --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-slow-request/slow-fetch/types.ts @@ -0,0 +1,15 @@ +export type RandomNumberRequestStateValue = + | { + error: string; + status: "error"; + timestamp: number; + } + | { + data: number; + status: "success"; + timestamp: number; + } + | { + status: "pending"; + timestamp: number; + }; diff --git a/templates/next-starter-with-examples/app/examples/new-api-transaction/frames/route.tsx b/templates/next-starter-with-examples/app/examples/new-api-transaction/frames/route.tsx new file mode 100644 index 000000000..8a1587891 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-transaction/frames/route.tsx @@ -0,0 +1,49 @@ +/* eslint-disable react/jsx-key */ +import { Button } from "frames.js/next"; +import { createFrames } from "frames.js/next"; + +const frames = createFrames({ + basePath: "/examples/new-api-transaction", +}); + +const handleRequest = frames(async (ctx) => { + if (ctx.message?.transactionId) { + return { + image: ( +
+ Transaction submitted! {ctx.message.transactionId} +
+ ), + imageOptions: { + aspectRatio: "1:1", + }, + buttons: [ + , + ], + }; + } + + return { + image: ( +
+ Rent farcaster storage +
+ ), + imageOptions: { + aspectRatio: "1:1", + }, + buttons: [ + , + ], + }; +}); + +export const GET = handleRequest; +export const POST = handleRequest; diff --git a/templates/next-starter-with-examples/app/examples/new-api-transaction/page.tsx b/templates/next-starter-with-examples/app/examples/new-api-transaction/page.tsx new file mode 100644 index 000000000..97fd5987f --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-transaction/page.tsx @@ -0,0 +1,33 @@ +import Link from "next/link"; +import { currentURL, vercelURL } from "../../utils"; +import { createDebugUrl } from "../../debug"; +import type { Metadata } from "next"; +import { fetchMetadata } from "frames.js/next"; + +export async function generateMetadata(): Promise { + return { + title: "New api example", + description: "This is a new api example", + other: { + ...(await fetchMetadata( + new URL( + "/examples/new-api-transaction/frames", + vercelURL() || "http://localhost:3000" + ) + )), + }, + }; +} + +export default async function Home() { + const url = currentURL("/examples/new-api-transaction"); + + return ( +
+ Rent farcaster storage example{" "} + + Debug + +
+ ); +} diff --git a/templates/next-starter-with-examples/app/examples/new-api-transaction/txdata/contracts/storage-registry.ts b/templates/next-starter-with-examples/app/examples/new-api-transaction/txdata/contracts/storage-registry.ts new file mode 100644 index 000000000..3f7e362b3 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-transaction/txdata/contracts/storage-registry.ts @@ -0,0 +1,814 @@ +export const storageRegistryABI = [ + { + inputs: [ + { + internalType: "contract AggregatorV3Interface", + name: "_priceFeed", + type: "address", + }, + { + internalType: "contract AggregatorV3Interface", + name: "_uptimeFeed", + type: "address", + }, + { + internalType: "uint256", + name: "_initialUsdUnitPrice", + type: "uint256", + }, + { internalType: "uint256", name: "_initialMaxUnits", type: "uint256" }, + { internalType: "address", name: "_initialVault", type: "address" }, + { internalType: "address", name: "_initialRoleAdmin", type: "address" }, + { internalType: "address", name: "_initialOwner", type: "address" }, + { internalType: "address", name: "_initialOperator", type: "address" }, + { internalType: "address", name: "_initialTreasurer", type: "address" }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { inputs: [], name: "CallFailed", type: "error" }, + { inputs: [], name: "ContractDeprecated", type: "error" }, + { inputs: [], name: "ExceedsCapacity", type: "error" }, + { inputs: [], name: "GracePeriodNotOver", type: "error" }, + { inputs: [], name: "IncompleteRound", type: "error" }, + { inputs: [], name: "InvalidAddress", type: "error" }, + { inputs: [], name: "InvalidAmount", type: "error" }, + { inputs: [], name: "InvalidBatchInput", type: "error" }, + { inputs: [], name: "InvalidDeprecationTimestamp", type: "error" }, + { inputs: [], name: "InvalidFixedPrice", type: "error" }, + { inputs: [], name: "InvalidMaxAnswer", type: "error" }, + { inputs: [], name: "InvalidMinAnswer", type: "error" }, + { inputs: [], name: "InvalidPayment", type: "error" }, + { inputs: [], name: "InvalidPrice", type: "error" }, + { inputs: [], name: "InvalidRangeInput", type: "error" }, + { inputs: [], name: "InvalidRoundTimestamp", type: "error" }, + { inputs: [], name: "NotOperator", type: "error" }, + { inputs: [], name: "NotOwner", type: "error" }, + { inputs: [], name: "NotTreasurer", type: "error" }, + { inputs: [], name: "PriceOutOfBounds", type: "error" }, + { inputs: [], name: "SequencerDown", type: "error" }, + { inputs: [], name: "StaleAnswer", type: "error" }, + { inputs: [], name: "Unauthorized", type: "error" }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "Paused", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "payer", + type: "address", + }, + { indexed: true, internalType: "uint256", name: "fid", type: "uint256" }, + { + indexed: false, + internalType: "uint256", + name: "units", + type: "uint256", + }, + ], + name: "Rent", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "role", type: "bytes32" }, + { + indexed: true, + internalType: "bytes32", + name: "previousAdminRole", + type: "bytes32", + }, + { + indexed: true, + internalType: "bytes32", + name: "newAdminRole", + type: "bytes32", + }, + ], + name: "RoleAdminChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "role", type: "bytes32" }, + { + indexed: true, + internalType: "address", + name: "account", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "RoleGranted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "role", type: "bytes32" }, + { + indexed: true, + internalType: "address", + name: "account", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "RoleRevoked", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldDuration", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newDuration", + type: "uint256", + }, + ], + name: "SetCacheDuration", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldTimestamp", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newTimestamp", + type: "uint256", + }, + ], + name: "SetDeprecationTimestamp", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldPrice", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newPrice", + type: "uint256", + }, + ], + name: "SetFixedEthUsdPrice", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldPeriod", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newPeriod", + type: "uint256", + }, + ], + name: "SetGracePeriod", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldAge", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newAge", + type: "uint256", + }, + ], + name: "SetMaxAge", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldPrice", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newPrice", + type: "uint256", + }, + ], + name: "SetMaxAnswer", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldMax", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newMax", + type: "uint256", + }, + ], + name: "SetMaxUnits", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldPrice", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newPrice", + type: "uint256", + }, + ], + name: "SetMinAnswer", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldPrice", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newPrice", + type: "uint256", + }, + ], + name: "SetPrice", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldFeed", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newFeed", + type: "address", + }, + ], + name: "SetPriceFeed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldFeed", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newFeed", + type: "address", + }, + ], + name: "SetUptimeFeed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldVault", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newVault", + type: "address", + }, + ], + name: "SetVault", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "Unpaused", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "to", type: "address" }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "Withdraw", + type: "event", + }, + { + inputs: [], + name: "DEFAULT_ADMIN_ROLE", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "VERSION", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256[]", name: "fids", type: "uint256[]" }, + { internalType: "uint256", name: "units", type: "uint256" }, + ], + name: "batchCredit", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256[]", name: "fids", type: "uint256[]" }, + { internalType: "uint256[]", name: "units", type: "uint256[]" }, + ], + name: "batchRent", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "start", type: "uint256" }, + { internalType: "uint256", name: "end", type: "uint256" }, + { internalType: "uint256", name: "units", type: "uint256" }, + ], + name: "continuousCredit", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "fid", type: "uint256" }, + { internalType: "uint256", name: "units", type: "uint256" }, + ], + name: "credit", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "deprecationTimestamp", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "ethUsdPrice", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "fixedEthUsdPrice", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "role", type: "bytes32" }], + name: "getRoleAdmin", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "uint256", name: "index", type: "uint256" }, + ], + name: "getRoleMember", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "role", type: "bytes32" }], + name: "getRoleMemberCount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "grantRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "hasRole", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "lastPriceFeedUpdateBlock", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "lastPriceFeedUpdateTime", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "maxUnits", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "pause", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "paused", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "prevEthUsdPrice", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "units", type: "uint256" }], + name: "price", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "priceFeed", + outputs: [ + { + internalType: "contract AggregatorV3Interface", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "priceFeedCacheDuration", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "priceFeedMaxAge", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "priceFeedMaxAnswer", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "priceFeedMinAnswer", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "refreshPrice", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "renounceRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "fid", type: "uint256" }, + { internalType: "uint256", name: "units", type: "uint256" }, + ], + name: "rent", + outputs: [ + { internalType: "uint256", name: "overpayment", type: "uint256" }, + ], + stateMutability: "payable", + type: "function", + }, + { + inputs: [], + name: "rentedUnits", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "revokeRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "duration", type: "uint256" }], + name: "setCacheDuration", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "timestamp", type: "uint256" }], + name: "setDeprecationTimestamp", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "fixedPrice", type: "uint256" }], + name: "setFixedEthUsdPrice", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "period", type: "uint256" }], + name: "setGracePeriod", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "age", type: "uint256" }], + name: "setMaxAge", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "maxPrice", type: "uint256" }], + name: "setMaxAnswer", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "max", type: "uint256" }], + name: "setMaxUnits", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "minPrice", type: "uint256" }], + name: "setMinAnswer", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "usdPrice", type: "uint256" }], + name: "setPrice", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract AggregatorV3Interface", + name: "feed", + type: "address", + }, + ], + name: "setPriceFeed", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract AggregatorV3Interface", + name: "feed", + type: "address", + }, + ], + name: "setUptimeFeed", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "vaultAddr", type: "address" }], + name: "setVault", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes4", name: "interfaceId", type: "bytes4" }], + name: "supportsInterface", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "unitPrice", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "unpause", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "uptimeFeed", + outputs: [ + { + internalType: "contract AggregatorV3Interface", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "uptimeFeedGracePeriod", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "usdUnitPrice", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "vault", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "amount", type: "uint256" }], + name: "withdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +] as const; diff --git a/templates/next-starter-with-examples/app/examples/new-api-transaction/txdata/route.ts b/templates/next-starter-with-examples/app/examples/new-api-transaction/txdata/route.ts new file mode 100644 index 000000000..c574ab85c --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api-transaction/txdata/route.ts @@ -0,0 +1,58 @@ +import { STORAGE_REGISTRY_ADDRESS } from "@farcaster/core"; +import { TransactionTargetResponse } from "frames.js"; +import { getFrameMessage } from "frames.js/next/server"; +import { NextRequest, NextResponse } from "next/server"; +import { + Abi, + createPublicClient, + encodeFunctionData, + getContract, + http, +} from "viem"; +import { optimism } from "viem/chains"; +import { storageRegistryABI } from "./contracts/storage-registry"; + +export async function POST( + req: NextRequest +): Promise> { + const json = await req.json(); + + const frameMessage = await getFrameMessage(json); + + if (!frameMessage) { + throw new Error("No frame message"); + } + + // Get current storage price + const units = 1n; + + const calldata = encodeFunctionData({ + abi: storageRegistryABI, + functionName: "rent", + args: [BigInt(frameMessage.requesterFid), units], + }); + + const publicClient = createPublicClient({ + chain: optimism, + transport: http(), + }); + + const storageRegistry = getContract({ + address: STORAGE_REGISTRY_ADDRESS, + abi: storageRegistryABI, + client: publicClient, + }); + + const unitPrice = await storageRegistry.read.price([units]); + + return NextResponse.json({ + chainId: "eip155:10", // OP Mainnet 10 + method: "eth_sendTransaction", + params: { + abi: storageRegistryABI as Abi, + to: STORAGE_REGISTRY_ADDRESS, + data: calldata, + value: unitPrice.toString(), + }, + }); +} diff --git a/templates/next-starter-with-examples/app/examples/new-api/frames/frames.ts b/templates/next-starter-with-examples/app/examples/new-api/frames/frames.ts new file mode 100644 index 000000000..3fdf38d47 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api/frames/frames.ts @@ -0,0 +1,5 @@ +import { createFrames } from "frames.js/next"; + +export const frames = createFrames({ + basePath: "/examples/new-api/frames", +}); diff --git a/templates/next-starter-with-examples/app/examples/new-api/frames/next/route.tsx b/templates/next-starter-with-examples/app/examples/new-api/frames/next/route.tsx new file mode 100644 index 000000000..9c6ab573a --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api/frames/next/route.tsx @@ -0,0 +1,21 @@ +/* eslint-disable react/jsx-key */ +import { Button } from "frames.js/next"; +import { frames } from "../frames"; + +const handleRequest = frames(async (ctx) => { + return { + image: ( + + This is next frame and you clicked button:{" "} + {ctx.pressedButton ? "✅" : "❌"} + + ), + buttons: [ + , + ], + }; +}); + +export const POST = handleRequest; diff --git a/templates/next-starter-with-examples/app/examples/new-api/frames/route.tsx b/templates/next-starter-with-examples/app/examples/new-api/frames/route.tsx new file mode 100644 index 000000000..4caad2833 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api/frames/route.tsx @@ -0,0 +1,24 @@ +/* eslint-disable react/jsx-key */ +import { Button } from "frames.js/next"; +import { frames } from "./frames"; + +const handleRequest = frames(async (ctx) => { + return { + image: ( + + Hello there: {ctx.pressedButton ? "✅" : "❌"} + {ctx.message?.inputText ? `, Typed: ${ctx.message?.inputText}` : ""} + + ), + buttons: [ + , + , + ], + textInput: "Type something!", + }; +}); + +export const GET = handleRequest; +export const POST = handleRequest; diff --git a/templates/next-starter-with-examples/app/examples/new-api/page.tsx b/templates/next-starter-with-examples/app/examples/new-api/page.tsx new file mode 100644 index 000000000..b8a5aef52 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/new-api/page.tsx @@ -0,0 +1,33 @@ +import Link from "next/link"; +import { currentURL, vercelURL } from "../../utils"; +import { createDebugUrl } from "../../debug"; +import type { Metadata } from "next"; +import { fetchMetadata } from "frames.js/next"; + +export async function generateMetadata(): Promise { + return { + title: "New api example", + description: "This is a new api example", + other: { + ...(await fetchMetadata( + new URL( + "/examples/new-api/frames", + vercelURL() || "http://localhost:3000" + ) + )), + }, + }; +} + +export default async function Home() { + const url = currentURL("/examples/new-api"); + + return ( +
+ New api example.{" "} + + Debug + +
+ ); +} diff --git a/templates/next-starter-with-examples/app/examples/only-followers-can-mint/frames/route.ts b/templates/next-starter-with-examples/app/examples/only-followers-can-mint/frames/route.ts new file mode 100644 index 000000000..2b10a621f --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/only-followers-can-mint/frames/route.ts @@ -0,0 +1 @@ +export { POST } from "frames.js/next/server"; diff --git a/templates/next-starter-with-examples/app/examples/only-followers-can-mint/page.tsx b/templates/next-starter-with-examples/app/examples/only-followers-can-mint/page.tsx new file mode 100644 index 000000000..7b0787184 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/only-followers-can-mint/page.tsx @@ -0,0 +1,115 @@ +import { + FrameButton, + FrameContainer, + FrameImage, + FrameReducer, + NextServerPageProps, + getFrameMessage, + getPreviousFrame, + useFramesReducer, +} from "frames.js/next/server"; +import Link from "next/link"; +import { getTokenUrl } from "frames.js"; +import { zora } from "viem/chains"; +import { DEFAULT_DEBUGGER_HUB_URL, createDebugUrl } from "../../debug"; +import { currentURL } from "../../utils"; + +type State = + | { + page: "initial"; + } + | { page: "result" }; + +const initialState: State = { page: "initial" }; + +const reducer: FrameReducer = (state, action) => { + const buttonIndex = action.postBody?.untrustedData.buttonIndex; + + switch (state.page) { + case "initial": + return buttonIndex === 1 ? { page: "result" } : state; + case "result": + return buttonIndex === 1 ? { page: "initial" } : state; + default: + return { page: "initial" }; + } +}; + +// This is a react server component only +export default async function Home({ + params, + searchParams, +}: NextServerPageProps) { + const url = currentURL("/examples/slow-request"); + + const previousFrame = getPreviousFrame(searchParams); + + const frameMessage = await getFrameMessage(previousFrame.postBody, { + hubHttpUrl: DEFAULT_DEBUGGER_HUB_URL, + }); + + console.log("info: frameMessage is:", frameMessage); + + if (frameMessage && !frameMessage?.isValid) { + throw new Error("Invalid frame payload"); + } + + const [state, dispatch] = useFramesReducer( + reducer, + initialState, + previousFrame + ); + + // Here: do a server side side effect either sync or async (using await), such as minting an NFT if you want. + // example: load the users credentials & check they have an NFT + console.log("info: state is:", state); + + const initialPage = [ + +
+ You can mint if you follow the caster. +
+
, + Am I?, + ]; + + const resultPage = [ + +
+ {frameMessage?.requesterFollowsCaster + ? "You are following the caster." + : "You are not following the caster"} +
+
, + , + frameMessage?.requesterFollowsCaster ? ( + + Mint + + ) : null, + ]; + + // then, when done, return next frame + return ( +
+ Only followers can mint example.{" "} + Debug + + {state.page === "initial" ? initialPage : resultPage} + +
+ ); +} diff --git a/templates/next-starter-with-examples/app/examples/page.tsx b/templates/next-starter-with-examples/app/examples/page.tsx index 63bb4ab9f..6e83231f7 100644 --- a/templates/next-starter-with-examples/app/examples/page.tsx +++ b/templates/next-starter-with-examples/app/examples/page.tsx @@ -2,7 +2,59 @@ import Link from "next/link"; export default function ExamplesIndexPage() { return ( -
+
+ Frames.js v0.9 +
    +
  • + + Basic + +
  • +
  • + + Transactions + +
  • +
  • + + Multi Page + +
  • +
  • + + Mint button + +
  • +
  • + + Only followers can mint + +
  • +
  • + + Post redirect + +
  • +
  • + + Open Frames + +
  • +
  • + + Caching + +
  • +
  • + + Slow requests + +
  • +
+ Frames.js v0.8 and below
  • @@ -34,6 +86,11 @@ export default function ExamplesIndexPage() { Multi protocol
  • +
  • + + Only followers can mint + +
  • Slow request @@ -44,6 +101,11 @@ export default function ExamplesIndexPage() { User data
  • +
  • + + Page router + +
); diff --git a/templates/next-starter-with-examples/app/examples/transaction/page.tsx b/templates/next-starter-with-examples/app/examples/transaction/page.tsx index 6acddac89..560f73953 100644 --- a/templates/next-starter-with-examples/app/examples/transaction/page.tsx +++ b/templates/next-starter-with-examples/app/examples/transaction/page.tsx @@ -4,12 +4,13 @@ import { FrameImage, FrameReducer, NextServerPageProps, + getFrameMessage, getPreviousFrame, useFramesReducer, } from "frames.js/next/server"; import Link from "next/link"; import { currentURL } from "../../utils"; -import { createDebugUrl } from "../../debug"; +import { DEFAULT_DEBUGGER_HUB_URL, createDebugUrl } from "../../debug"; type State = { pageIndex: number; @@ -27,8 +28,36 @@ const reducer: FrameReducer = (state, action) => { export default async function Home({ searchParams }: NextServerPageProps) { const url = currentURL("/examples/transaction"); const previousFrame = getPreviousFrame(searchParams); + const [state] = useFramesReducer(reducer, initialState, previousFrame); + const frameMessage = await getFrameMessage(previousFrame.postBody, { + hubHttpUrl: DEFAULT_DEBUGGER_HUB_URL, + }); + + if (frameMessage?.transactionId) { + return ( + + +
+ Transaction submitted! {frameMessage.transactionId} +
+
+ + View on block explorer + +
+ ); + } + // then, when done, return next frame return (
diff --git a/templates/next-starter-with-examples/app/examples/transaction/txdata/contracts/storage-registry.ts b/templates/next-starter-with-examples/app/examples/transaction/txdata/contracts/storage-registry.ts new file mode 100644 index 000000000..3f7e362b3 --- /dev/null +++ b/templates/next-starter-with-examples/app/examples/transaction/txdata/contracts/storage-registry.ts @@ -0,0 +1,814 @@ +export const storageRegistryABI = [ + { + inputs: [ + { + internalType: "contract AggregatorV3Interface", + name: "_priceFeed", + type: "address", + }, + { + internalType: "contract AggregatorV3Interface", + name: "_uptimeFeed", + type: "address", + }, + { + internalType: "uint256", + name: "_initialUsdUnitPrice", + type: "uint256", + }, + { internalType: "uint256", name: "_initialMaxUnits", type: "uint256" }, + { internalType: "address", name: "_initialVault", type: "address" }, + { internalType: "address", name: "_initialRoleAdmin", type: "address" }, + { internalType: "address", name: "_initialOwner", type: "address" }, + { internalType: "address", name: "_initialOperator", type: "address" }, + { internalType: "address", name: "_initialTreasurer", type: "address" }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { inputs: [], name: "CallFailed", type: "error" }, + { inputs: [], name: "ContractDeprecated", type: "error" }, + { inputs: [], name: "ExceedsCapacity", type: "error" }, + { inputs: [], name: "GracePeriodNotOver", type: "error" }, + { inputs: [], name: "IncompleteRound", type: "error" }, + { inputs: [], name: "InvalidAddress", type: "error" }, + { inputs: [], name: "InvalidAmount", type: "error" }, + { inputs: [], name: "InvalidBatchInput", type: "error" }, + { inputs: [], name: "InvalidDeprecationTimestamp", type: "error" }, + { inputs: [], name: "InvalidFixedPrice", type: "error" }, + { inputs: [], name: "InvalidMaxAnswer", type: "error" }, + { inputs: [], name: "InvalidMinAnswer", type: "error" }, + { inputs: [], name: "InvalidPayment", type: "error" }, + { inputs: [], name: "InvalidPrice", type: "error" }, + { inputs: [], name: "InvalidRangeInput", type: "error" }, + { inputs: [], name: "InvalidRoundTimestamp", type: "error" }, + { inputs: [], name: "NotOperator", type: "error" }, + { inputs: [], name: "NotOwner", type: "error" }, + { inputs: [], name: "NotTreasurer", type: "error" }, + { inputs: [], name: "PriceOutOfBounds", type: "error" }, + { inputs: [], name: "SequencerDown", type: "error" }, + { inputs: [], name: "StaleAnswer", type: "error" }, + { inputs: [], name: "Unauthorized", type: "error" }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "Paused", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "payer", + type: "address", + }, + { indexed: true, internalType: "uint256", name: "fid", type: "uint256" }, + { + indexed: false, + internalType: "uint256", + name: "units", + type: "uint256", + }, + ], + name: "Rent", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "role", type: "bytes32" }, + { + indexed: true, + internalType: "bytes32", + name: "previousAdminRole", + type: "bytes32", + }, + { + indexed: true, + internalType: "bytes32", + name: "newAdminRole", + type: "bytes32", + }, + ], + name: "RoleAdminChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "role", type: "bytes32" }, + { + indexed: true, + internalType: "address", + name: "account", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "RoleGranted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "role", type: "bytes32" }, + { + indexed: true, + internalType: "address", + name: "account", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "RoleRevoked", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldDuration", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newDuration", + type: "uint256", + }, + ], + name: "SetCacheDuration", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldTimestamp", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newTimestamp", + type: "uint256", + }, + ], + name: "SetDeprecationTimestamp", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldPrice", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newPrice", + type: "uint256", + }, + ], + name: "SetFixedEthUsdPrice", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldPeriod", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newPeriod", + type: "uint256", + }, + ], + name: "SetGracePeriod", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldAge", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newAge", + type: "uint256", + }, + ], + name: "SetMaxAge", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldPrice", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newPrice", + type: "uint256", + }, + ], + name: "SetMaxAnswer", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldMax", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newMax", + type: "uint256", + }, + ], + name: "SetMaxUnits", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldPrice", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newPrice", + type: "uint256", + }, + ], + name: "SetMinAnswer", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldPrice", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newPrice", + type: "uint256", + }, + ], + name: "SetPrice", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldFeed", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newFeed", + type: "address", + }, + ], + name: "SetPriceFeed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldFeed", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newFeed", + type: "address", + }, + ], + name: "SetUptimeFeed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldVault", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newVault", + type: "address", + }, + ], + name: "SetVault", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "Unpaused", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "to", type: "address" }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "Withdraw", + type: "event", + }, + { + inputs: [], + name: "DEFAULT_ADMIN_ROLE", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "VERSION", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256[]", name: "fids", type: "uint256[]" }, + { internalType: "uint256", name: "units", type: "uint256" }, + ], + name: "batchCredit", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256[]", name: "fids", type: "uint256[]" }, + { internalType: "uint256[]", name: "units", type: "uint256[]" }, + ], + name: "batchRent", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "start", type: "uint256" }, + { internalType: "uint256", name: "end", type: "uint256" }, + { internalType: "uint256", name: "units", type: "uint256" }, + ], + name: "continuousCredit", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "fid", type: "uint256" }, + { internalType: "uint256", name: "units", type: "uint256" }, + ], + name: "credit", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "deprecationTimestamp", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "ethUsdPrice", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "fixedEthUsdPrice", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "role", type: "bytes32" }], + name: "getRoleAdmin", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "uint256", name: "index", type: "uint256" }, + ], + name: "getRoleMember", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "role", type: "bytes32" }], + name: "getRoleMemberCount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "grantRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "hasRole", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "lastPriceFeedUpdateBlock", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "lastPriceFeedUpdateTime", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "maxUnits", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "pause", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "paused", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "prevEthUsdPrice", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "units", type: "uint256" }], + name: "price", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "priceFeed", + outputs: [ + { + internalType: "contract AggregatorV3Interface", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "priceFeedCacheDuration", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "priceFeedMaxAge", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "priceFeedMaxAnswer", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "priceFeedMinAnswer", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "refreshPrice", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "renounceRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "fid", type: "uint256" }, + { internalType: "uint256", name: "units", type: "uint256" }, + ], + name: "rent", + outputs: [ + { internalType: "uint256", name: "overpayment", type: "uint256" }, + ], + stateMutability: "payable", + type: "function", + }, + { + inputs: [], + name: "rentedUnits", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "revokeRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "duration", type: "uint256" }], + name: "setCacheDuration", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "timestamp", type: "uint256" }], + name: "setDeprecationTimestamp", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "fixedPrice", type: "uint256" }], + name: "setFixedEthUsdPrice", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "period", type: "uint256" }], + name: "setGracePeriod", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "age", type: "uint256" }], + name: "setMaxAge", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "maxPrice", type: "uint256" }], + name: "setMaxAnswer", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "max", type: "uint256" }], + name: "setMaxUnits", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "minPrice", type: "uint256" }], + name: "setMinAnswer", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "usdPrice", type: "uint256" }], + name: "setPrice", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract AggregatorV3Interface", + name: "feed", + type: "address", + }, + ], + name: "setPriceFeed", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract AggregatorV3Interface", + name: "feed", + type: "address", + }, + ], + name: "setUptimeFeed", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "vaultAddr", type: "address" }], + name: "setVault", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes4", name: "interfaceId", type: "bytes4" }], + name: "supportsInterface", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "unitPrice", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "unpause", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "uptimeFeed", + outputs: [ + { + internalType: "contract AggregatorV3Interface", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "uptimeFeedGracePeriod", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "usdUnitPrice", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "vault", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "amount", type: "uint256" }], + name: "withdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +] as const; diff --git a/templates/next-starter-with-examples/app/examples/transaction/txdata/route.ts b/templates/next-starter-with-examples/app/examples/transaction/txdata/route.ts index b9c93f45d..c574ab85c 100644 --- a/templates/next-starter-with-examples/app/examples/transaction/txdata/route.ts +++ b/templates/next-starter-with-examples/app/examples/transaction/txdata/route.ts @@ -1,17 +1,58 @@ +import { STORAGE_REGISTRY_ADDRESS } from "@farcaster/core"; import { TransactionTargetResponse } from "frames.js"; +import { getFrameMessage } from "frames.js/next/server"; import { NextRequest, NextResponse } from "next/server"; +import { + Abi, + createPublicClient, + encodeFunctionData, + getContract, + http, +} from "viem"; +import { optimism } from "viem/chains"; +import { storageRegistryABI } from "./contracts/storage-registry"; -export function POST( +export async function POST( req: NextRequest -): NextResponse { +): Promise> { + const json = await req.json(); + + const frameMessage = await getFrameMessage(json); + + if (!frameMessage) { + throw new Error("No frame message"); + } + + // Get current storage price + const units = 1n; + + const calldata = encodeFunctionData({ + abi: storageRegistryABI, + functionName: "rent", + args: [BigInt(frameMessage.requesterFid), units], + }); + + const publicClient = createPublicClient({ + chain: optimism, + transport: http(), + }); + + const storageRegistry = getContract({ + address: STORAGE_REGISTRY_ADDRESS, + abi: storageRegistryABI, + client: publicClient, + }); + + const unitPrice = await storageRegistry.read.price([units]); + return NextResponse.json({ - chainId: "eip155:10", + chainId: "eip155:10", // OP Mainnet 10 method: "eth_sendTransaction", params: { - abi: [], // "function rent(uint256 fid, uint256 units) payable" - to: "0x00000000fcCe7f938e7aE6D3c335bD6a1a7c593D", - data: "0x783a112b0000000000000000000000000000000000000000000000000000000000000e250000000000000000000000000000000000000000000000000000000000000001", - value: "984316556204476", + abi: storageRegistryABI as Abi, + to: STORAGE_REGISTRY_ADDRESS, + data: calldata, + value: unitPrice.toString(), }, }); } diff --git a/templates/next-starter-with-examples/app/page.tsx b/templates/next-starter-with-examples/app/page.tsx index 7463eabb8..c34727389 100644 --- a/templates/next-starter-with-examples/app/page.tsx +++ b/templates/next-starter-with-examples/app/page.tsx @@ -60,6 +60,10 @@ export default async function Home({ searchParams }: NextServerPageProps) { the html meta tags (inspect source).{" "} Debug + {" "} + or see{" "} + + other examples =18.17.0" }, "devDependencies": { - "@frames.js/debugger": "^0.1.8", + "@frames.js/debugger": "^0.1.9", "@types/node": "^18.17.0", "@types/react": "^18.2.0", "@types/react-dom": "^18.2.0", @@ -34,7 +34,7 @@ "concurrently": "^8.2.2", "dotenv": "^16.4.5", "eslint": "^8.56.0", - "eslint-config-next": "14.1.0", + "eslint-config-next": "^14.1.0", "postcss": "^8", "tailwindcss": "^3.3.0", "typescript": "^5.3.3" diff --git a/templates/next-utils-starter/CHANGELOG.md b/templates/next-utils-starter/CHANGELOG.md deleted file mode 100644 index a7f7fc853..000000000 --- a/templates/next-utils-starter/CHANGELOG.md +++ /dev/null @@ -1,60 +0,0 @@ -# utils-starter - -## 1.1.2 - -### Patch Changes - -- Updated dependencies [72e6617] -- Updated dependencies [7ccc562] - - frames.js@0.8.0 - -## 1.1.1 - -### Patch Changes - -- Updated dependencies [01fc5fe] -- Updated dependencies [60c6e56] -- Updated dependencies [e335829] -- Updated dependencies [eee74a9] - - frames.js@0.7.0 - -## 1.1.0 - -### Minor Changes - -- 845b30c: refactor: make frame validation errors arbitraty, remove unnecessary validateFrame function - -### Patch Changes - -- Updated dependencies [845b30c] -- Updated dependencies [ce1cec6] -- Updated dependencies [845b30c] - - frames.js@0.6.0 - -## 1.0.4 - -### Patch Changes - -- Updated dependencies [40d2662] - - frames.js@0.5.0 - -## 1.0.3 - -### Patch Changes - -- Updated dependencies [ccd3302] - - frames.js@0.4.0 - -## 1.0.2 - -### Patch Changes - -- Updated dependencies [03d041e] - - frames.js@0.3.0 - -## 1.0.1 - -### Patch Changes - -- Updated dependencies [608bac9] - - frames.js@0.2.0 diff --git a/templates/next-utils-starter/app/api/frame/route.ts b/templates/next-utils-starter/app/api/frame/route.ts new file mode 100644 index 000000000..28c07aff6 --- /dev/null +++ b/templates/next-utils-starter/app/api/frame/route.ts @@ -0,0 +1,55 @@ +import { + Frame, + getFrameHtml, + getFrameMessageFromRequestBody, + validateFrameMessage, +} from "frames.js"; +import { NextRequest, NextResponse } from "next/server"; +import { HOST, framePostUrl } from "../../constants"; + +export async function POST(request: NextRequest) { + const body = await request.json(); + + const untrustedMessage = getFrameMessageFromRequestBody(body); + + if (untrustedMessage.data?.frameActionBody?.buttonIndex === 2) { + const resp = NextResponse.redirect(`${HOST}/redirect`, 302); + return resp; + } + + const result = await validateFrameMessage(body); + + const { isValid, message } = result; + if (!isValid || !message) { + return new Response("Invalid message", { status: 400 }); + } + + const randomInt = Math.floor(Math.random() * 100); + const imageUrl = `https://picsum.photos/seed/${randomInt}/1146/600`; + + const frame: Frame = { + version: "vNext", + image: imageUrl, + buttons: [ + { + label: `Next (pressed by ${message?.data.fid})`, + action: "post", + }, + { + label: "Visit frames.js", + action: "post_redirect", + }, + ], + ogImage: imageUrl, + postUrl: framePostUrl, + }; + + const html = getFrameHtml(frame); + + return new Response(html, { + headers: { + "Content-Type": "text/html", + }, + status: 200, + }); +} diff --git a/templates/next-utils-starter/app/api/frame/route.tsx b/templates/next-utils-starter/app/api/frame/route.tsx deleted file mode 100644 index 186a3dcd9..000000000 --- a/templates/next-utils-starter/app/api/frame/route.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { - getFrameMessageFromRequestBody, - validateFrameMessage, -} from "frames.js"; -import { redirect } from "frames.js/core"; -import { createFrames, Button } from "frames.js/next"; - -const frames = createFrames(); - -const handleRequest = frames(async (ctx) => { - const body = await ctx.request.clone().json(); - - const untrustedMessage = getFrameMessageFromRequestBody(body); - - if (untrustedMessage.data?.frameActionBody?.buttonIndex === 2) { - return redirect(new URL("/redirect", ctx.url), { status: 302 }); - } - - const result = await validateFrameMessage(body); - - const { isValid, message } = result; - - if (!isValid || !message) { - return { - image: Invalid message, - }; - } - - const randomInt = Math.floor(Math.random() * 100); - const imageUrl = `https://picsum.photos/seed/${randomInt}/1146/600`; - - return { - image: imageUrl, - buttons: [ - , - , - ], - }; -}); - -export const GET = handleRequest; -export const POST = handleRequest; diff --git a/templates/next-utils-starter/app/layout.tsx b/templates/next-utils-starter/app/layout.tsx index 11369f8f6..80399e5c8 100644 --- a/templates/next-utils-starter/app/layout.tsx +++ b/templates/next-utils-starter/app/layout.tsx @@ -1,23 +1,57 @@ -import { fetchMetadata } from "frames.js/next"; +import { type FrameFlattened, getFrameFlattened } from "frames.js"; import type { Metadata } from "next"; import { Inter } from "next/font/google"; -import { framePostUrl, ogImage } from "./constants"; +import { framePostUrl } from "./constants"; const inter = Inter({ subsets: ["latin"] }); +const imageUrl = "https://picsum.photos/seed/frames.js/1146/600"; + +/** + * Stripes undefined values from a `FrameFlattened` object and returns a new object with only the defined values + */ +function convertFlattenedFrameToMetadata( + frame: FrameFlattened +): Metadata["other"] { + const metadata: Metadata["other"] = {}; + + for (const [key, value] of Object.entries(frame)) { + if (value != null) { + metadata[key] = value; + } + } + + return metadata; +} + export const metadata: Metadata = { title: "Random Image Frame", description: "This is an example of a simple frame using frames.js", openGraph: { images: [ { - url: ogImage, + url: imageUrl, }, ], }, - other: { - ...(await fetchMetadata(new URL("/frames", framePostUrl))), - }, + other: convertFlattenedFrameToMetadata( + getFrameFlattened({ + image: imageUrl, + version: "vNext", + buttons: [ + { + label: "Next", + action: "post", + }, + { + label: "Visit frames.js", + action: "post_redirect", + }, + ], + inputText: "Type something", + postUrl: framePostUrl, + }) + ), }; export default function RootLayout({ diff --git a/templates/next-utils-starter/package.json b/templates/next-utils-starter/package.json index 4b67d3d75..f24b8c90d 100644 --- a/templates/next-utils-starter/package.json +++ b/templates/next-utils-starter/package.json @@ -1,7 +1,8 @@ { "name": "template-next-utils-starter", - "version": "1.1.2", + "version": "", "private": true, + "type": "module", "scripts": { "dev": "concurrently --kill-others \"next dev\" \"frames --url http://localhost:3000\"", "build": "next build", @@ -9,14 +10,14 @@ "lint": "next lint" }, "dependencies": { - "frames.js": "^0.9.1", + "frames.js": "^0.9.6", "next": "^14.0.4", "react": "^18.2.0", "react-dom": "^18.2.0" }, "devDependencies": { "@next/eslint-plugin-next": "^14.0.4", - "@frames.js/debugger": "^0.1.8", + "@frames.js/debugger": "^0.1.9", "@types/eslint": "^8.56.1", "@types/node": "^20.10.6", "@types/react": "^18.2.46", diff --git a/templates/next/app/frames/route.tsx b/templates/next/app/frames/route.tsx index 867a3e408..77dfeb590 100644 --- a/templates/next/app/frames/route.tsx +++ b/templates/next/app/frames/route.tsx @@ -40,7 +40,7 @@ const handleRequest = frames(async (ctx) => { Say GM
), - buttons: ctx.url.searchParams.has("saidGm") + buttons: !ctx.url.searchParams.has("saidGm") ? [ , + ] + : [], + }; +}); + +export const action = handleRequest; +export const loader = handleRequest; diff --git a/templates/remix/package.json b/templates/remix/package.json new file mode 100644 index 000000000..8a87821b3 --- /dev/null +++ b/templates/remix/package.json @@ -0,0 +1,36 @@ +{ + "name": "template-remix", + "version": "0.0.0", + "private": true, + "type": "module", + "engines": { + "node": ">=18.17.0" + }, + "dependencies": { + "@remix-run/node": "^2.8.1", + "@remix-run/react": "^2.8.1", + "@remix-run/serve": "^2.8.1", + "frames.js": "^0.9.6", + "isbot": "^4.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@frames.js/debugger": "^0.1.9", + "@remix-run/dev": "^2.8.1", + "@types/react": "^18.2.20", + "@types/react-dom": "^18.2.7", + "@typescript-eslint/eslint-plugin": "^6.7.4", + "@typescript-eslint/parser": "^6.7.4", + "concurrently": "^8.2.2", + "typescript": "^5.1.6", + "vite": "^5.1.0", + "vite-tsconfig-paths": "^4.2.1" + }, + "scripts": { + "build": "remix vite:build", + "dev": "concurrently \"remix vite:dev\" \"frames --url http://localhost:5173\"", + "start": "remix-serve ./build/server/index.js", + "typecheck": "tsc" + } +} diff --git a/templates/remix/tsconfig.json b/templates/remix/tsconfig.json new file mode 100644 index 000000000..9d87dd378 --- /dev/null +++ b/templates/remix/tsconfig.json @@ -0,0 +1,32 @@ +{ + "include": [ + "**/*.ts", + "**/*.tsx", + "**/.server/**/*.ts", + "**/.server/**/*.tsx", + "**/.client/**/*.ts", + "**/.client/**/*.tsx" + ], + "compilerOptions": { + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "types": ["@remix-run/node", "vite/client"], + "isolatedModules": true, + "esModuleInterop": true, + "jsx": "react-jsx", + "module": "ESNext", + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "target": "ES2022", + "strict": true, + "allowJs": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "baseUrl": ".", + "paths": { + "~/*": ["./app/*"] + }, + + // Vite takes care of building everything, not tsc. + "noEmit": true + } +} diff --git a/templates/remix/vite.config.ts b/templates/remix/vite.config.ts new file mode 100644 index 000000000..2b6aff987 --- /dev/null +++ b/templates/remix/vite.config.ts @@ -0,0 +1,10 @@ +import { vitePlugin as remix } from "@remix-run/dev"; +import { installGlobals } from "@remix-run/node"; +import { defineConfig } from "vite"; +import tsconfigPaths from "vite-tsconfig-paths"; + +installGlobals(); + +export default defineConfig({ + plugins: [remix(), tsconfigPaths()], +}); diff --git a/yarn.lock b/yarn.lock index 31d91e21c..c68988c96 100644 --- a/yarn.lock +++ b/yarn.lock @@ -38,7 +38,7 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.1.tgz#31c1f66435f2a9c329bb5716a6d6186c516c3742" integrity sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA== -"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.20.7", "@babel/core@^7.22.11", "@babel/core@^7.23.3", "@babel/core@^7.23.9": +"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.20.7", "@babel/core@^7.21.8", "@babel/core@^7.22.11", "@babel/core@^7.23.3", "@babel/core@^7.23.5", "@babel/core@^7.23.9": version "7.24.3" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.3.tgz#568864247ea10fbd4eff04dda1e05f9e2ea985c3" integrity sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ== @@ -68,7 +68,7 @@ eslint-visitor-keys "^2.1.0" semver "^6.3.1" -"@babel/generator@^7.24.1", "@babel/generator@^7.7.2": +"@babel/generator@^7.21.5", "@babel/generator@^7.24.1", "@babel/generator@^7.7.2": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.1.tgz#e67e06f68568a4ebf194d1c6014235344f0476d0" integrity sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A== @@ -78,6 +78,13 @@ "@jridgewell/trace-mapping" "^0.3.25" jsesc "^2.5.1" +"@babel/helper-annotate-as-pure@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" + integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-compilation-targets@^7.23.6": version "7.23.6" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" @@ -89,6 +96,21 @@ lru-cache "^5.1.1" semver "^6.3.1" +"@babel/helper-create-class-features-plugin@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.1.tgz#db58bf57137b623b916e24874ab7188d93d7f68f" + integrity sha512-1yJa9dX9g//V6fDebXoEfEsxkZHk3Hcbm+zLhyu6qVgYFLvmTALTeV+jNU9e5RnYtioBrGEOdoI2joMSNQ/+aA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-member-expression-to-functions" "^7.23.0" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-replace-supers" "^7.24.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + semver "^6.3.1" + "@babel/helper-environment-visitor@^7.22.20": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" @@ -109,6 +131,13 @@ dependencies: "@babel/types" "^7.22.5" +"@babel/helper-member-expression-to-functions@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz#9263e88cc5e41d39ec18c9a3e0eced59a3e7d366" + integrity sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA== + dependencies: + "@babel/types" "^7.23.0" + "@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.22.15": version "7.24.3" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz#6ac476e6d168c7c23ff3ba3cf4f7841d46ac8128" @@ -127,11 +156,27 @@ "@babel/helper-split-export-declaration" "^7.22.6" "@babel/helper-validator-identifier" "^7.22.20" +"@babel/helper-optimise-call-expression@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" + integrity sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.24.0", "@babel/helper-plugin-utils@^7.8.0": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz#945681931a52f15ce879fd5b86ce2dae6d3d7f2a" integrity sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w== +"@babel/helper-replace-supers@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz#7085bd19d4a0b7ed8f405c1ed73ccb70f323abc1" + integrity sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-member-expression-to-functions" "^7.23.0" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-simple-access@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" @@ -139,6 +184,13 @@ dependencies: "@babel/types" "^7.22.5" +"@babel/helper-skip-transparent-expression-wrappers@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" + integrity sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-split-export-declaration@^7.22.6": version "7.22.6" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" @@ -180,7 +232,7 @@ js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.24.0", "@babel/parser@^7.24.1": +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.21.8", "@babel/parser@^7.23.9", "@babel/parser@^7.24.0", "@babel/parser@^7.24.1": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.1.tgz#1e416d3627393fab1cb5b0f2f1796a100ae9133a" integrity sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg== @@ -206,6 +258,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.12.13" +"@babel/plugin-syntax-decorators@^7.22.10": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.24.1.tgz#71d9ad06063a6ac5430db126b5df48c70ee885fa" + integrity sha512-05RJdO/cCrtVWuAaSn1tS3bH8jbsJa/Y1uD186u6J4C/1mnHFxseeuWpsqr9anvo7TUulev7tm7GDwRV+VuhDw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/plugin-syntax-import-meta@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" @@ -220,7 +279,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.7.2": +"@babel/plugin-syntax-jsx@^7.21.4", "@babel/plugin-syntax-jsx@^7.24.1", "@babel/plugin-syntax-jsx@^7.7.2": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz#3f6ca04b8c841811dbc3c5c5f837934e0d626c10" integrity sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA== @@ -276,13 +335,22 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-typescript@^7.20.0", "@babel/plugin-syntax-typescript@^7.7.2": +"@babel/plugin-syntax-typescript@^7.20.0", "@babel/plugin-syntax-typescript@^7.24.1", "@babel/plugin-syntax-typescript@^7.7.2": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz#b3bcc51f396d15f3591683f90239de143c076844" integrity sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw== dependencies: "@babel/helper-plugin-utils" "^7.24.0" +"@babel/plugin-transform-modules-commonjs@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz#e71ba1d0d69e049a22bf90b3867e263823d3f1b9" + integrity sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw== + dependencies: + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-simple-access" "^7.22.5" + "@babel/plugin-transform-react-jsx-self@^7.23.3": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.1.tgz#a21d866d8167e752c6a7c4555dba8afcdfce6268" @@ -297,6 +365,27 @@ dependencies: "@babel/helper-plugin-utils" "^7.24.0" +"@babel/plugin-transform-typescript@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.1.tgz#5c05e28bb76c7dfe7d6c5bed9951324fd2d3ab07" + integrity sha512-liYSESjX2fZ7JyBFkYG78nfvHlMKE6IpNdTVnxmlYUR+j5ZLsitFbaAE+eJSK2zPPkNWNw4mXL51rQ8WrvdK0w== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.24.1" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/plugin-syntax-typescript" "^7.24.1" + +"@babel/preset-typescript@^7.21.5": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.24.1.tgz#89bdf13a3149a17b3b2a2c9c62547f06db8845ec" + integrity sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-validator-option" "^7.23.5" + "@babel/plugin-syntax-jsx" "^7.24.1" + "@babel/plugin-transform-modules-commonjs" "^7.24.1" + "@babel/plugin-transform-typescript" "^7.24.1" + "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.1", "@babel/runtime@^7.20.6", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.5", "@babel/runtime@^7.23.2", "@babel/runtime@^7.24.0", "@babel/runtime@^7.5.5": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.1.tgz#431f9a794d173b53720e69a6464abc6f0e2a5c57" @@ -313,7 +402,7 @@ "@babel/parser" "^7.24.0" "@babel/types" "^7.24.0" -"@babel/traverse@^7.24.1": +"@babel/traverse@^7.23.2", "@babel/traverse@^7.24.1": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.1.tgz#d65c36ac9dd17282175d1e4a3c49d5b7988f530c" integrity sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ== @@ -559,6 +648,31 @@ picocolors "^1.0.0" sisteransi "^1.0.5" +"@cloudflare/workerd-darwin-64@1.20240320.1": + version "1.20240320.1" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20240320.1.tgz#3cedf21172f54fad6d0e668e60152603968f3adc" + integrity sha512-ioG5k2M17xyiAlK/k3L21NZLMVeSHMjwlmGtZyCyzSLL5/zGINcgZ5yPLV0UuWiysw07/6Jjzm5Sx94hzMVybg== + +"@cloudflare/workerd-darwin-arm64@1.20240320.1": + version "1.20240320.1" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20240320.1.tgz#e90828f5ef2ec4b27f5b75178d21490aba631a72" + integrity sha512-Ga6RDdnFEIsN4WuWsaP9bLGvK9K7pEIVoSIgmw6vweVlD8UK/a2MPGrsF1ogwdeCTCOMY8wUh9poL/Yu48IPpg== + +"@cloudflare/workerd-linux-64@1.20240320.1": + version "1.20240320.1" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20240320.1.tgz#45fbece24a51c6e7ed314e9a87a04c8dc4cb6891" + integrity sha512-KFof5H8eU0NXv+pUAU7Lk/OLtOmfsioTJqu0v6kPL7QsTGsgzj5sEQNcQ8DONSze549Yflu5W00qpA2cPz9eWQ== + +"@cloudflare/workerd-linux-arm64@1.20240320.1": + version "1.20240320.1" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20240320.1.tgz#43f487d1a59019c9636fc31558f0e6ebcdbe4c5e" + integrity sha512-t+kGc6dGdkKvVMGcHCPhlCsUZF5dj8xbAFvLB7DAJ8T79ys30rmY2Lu/C8vKlhjH9TJhbzgKmPaJ0wC/K4euvw== + +"@cloudflare/workerd-windows-64@1.20240320.1": + version "1.20240320.1" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20240320.1.tgz#c2c5e6e82056a49453ce06133f106c504273ac20" + integrity sha512-9xDylCOsuzWqGuANkuUByiJ5RHeMqgw37FiI7rn8I6zdGAc/alOB9B4Bh7B73WC2uEpFL+XCEjcHZ6NmsO4NaQ== + "@coinbase/wallet-sdk@3.9.1": version "3.9.1" resolved "https://registry.yarnpkg.com/@coinbase/wallet-sdk/-/wallet-sdk-3.9.1.tgz#503a14671bb392d653623ef2340934e213ac971f" @@ -574,6 +688,13 @@ preact "^10.16.0" sha.js "^2.4.11" +"@cspotcode/source-map-support@0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + "@emotion/babel-plugin@^11.11.0": version "11.11.0" resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz#c2d872b6a7767a9d176d007f5b31f7d504bb5d6c" @@ -691,6 +812,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz#a70f4ac11c6a1dfc18b8bbb13284155d933b9537" integrity sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g== +"@esbuild/android-arm64@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.6.tgz#b11bd4e4d031bb320c93c83c137797b2be5b403b" + integrity sha512-YnYSCceN/dUzUr5kdtUzB+wZprCafuD89Hs0Aqv9QSdwhYQybhXTaSTcrl6X/aWThn1a/j0eEpUBGOE7269REg== + "@esbuild/android-arm64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz#7ad65a36cfdb7e0d429c353e00f680d737c2aed4" @@ -701,6 +827,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz#db1c9202a5bc92ea04c7b6840f1bbe09ebf9e6b9" integrity sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg== +"@esbuild/android-arm@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.6.tgz#ac6b5674da2149997f6306b3314dae59bbe0ac26" + integrity sha512-bSC9YVUjADDy1gae8RrioINU6e1lCkg3VGVwm0QQ2E1CWcC4gnMce9+B6RpxuSsrsXsk1yojn7sp1fnG8erE2g== + "@esbuild/android-arm@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.19.12.tgz#b0c26536f37776162ca8bde25e42040c203f2824" @@ -711,6 +842,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.20.2.tgz#3b488c49aee9d491c2c8f98a909b785870d6e995" integrity sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w== +"@esbuild/android-x64@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.6.tgz#18c48bf949046638fc209409ff684c6bb35a5462" + integrity sha512-MVcYcgSO7pfu/x34uX9u2QIZHmXAB7dEiLQC5bBl5Ryqtpj9lT2sg3gNDEsrPEmimSJW2FXIaxqSQ501YLDsZQ== + "@esbuild/android-x64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.19.12.tgz#cb13e2211282012194d89bf3bfe7721273473b3d" @@ -721,6 +857,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.20.2.tgz#3b1628029e5576249d2b2d766696e50768449f98" integrity sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg== +"@esbuild/darwin-arm64@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.6.tgz#b3fe19af1e4afc849a07c06318124e9c041e0646" + integrity sha512-bsDRvlbKMQMt6Wl08nHtFz++yoZHsyTOxnjfB2Q95gato+Yi4WnRl13oC2/PJJA9yLCoRv9gqT/EYX0/zDsyMA== + "@esbuild/darwin-arm64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz#cbee41e988020d4b516e9d9e44dd29200996275e" @@ -731,6 +872,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz#6e8517a045ddd86ae30c6608c8475ebc0c4000bb" integrity sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA== +"@esbuild/darwin-x64@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.6.tgz#f4dacd1ab21e17b355635c2bba6a31eba26ba569" + integrity sha512-xh2A5oPrYRfMFz74QXIQTQo8uA+hYzGWJFoeTE8EvoZGHb+idyV4ATaukaUvnnxJiauhs/fPx3vYhU4wiGfosg== + "@esbuild/darwin-x64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz#e37d9633246d52aecf491ee916ece709f9d5f4cd" @@ -741,6 +887,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz#90ed098e1f9dd8a9381695b207e1cff45540a0d0" integrity sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA== +"@esbuild/freebsd-arm64@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.6.tgz#ea4531aeda70b17cbe0e77b0c5c36298053855b4" + integrity sha512-EnUwjRc1inT4ccZh4pB3v1cIhohE2S4YXlt1OvI7sw/+pD+dIE4smwekZlEPIwY6PhU6oDWwITrQQm5S2/iZgg== + "@esbuild/freebsd-arm64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz#1ee4d8b682ed363b08af74d1ea2b2b4dbba76487" @@ -751,6 +902,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz#d71502d1ee89a1130327e890364666c760a2a911" integrity sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw== +"@esbuild/freebsd-x64@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.6.tgz#1896170b3c9f63c5e08efdc1f8abc8b1ed7af29f" + integrity sha512-Uh3HLWGzH6FwpviUcLMKPCbZUAFzv67Wj5MTwK6jn89b576SR2IbEp+tqUHTr8DIl0iDmBAf51MVaP7pw6PY5Q== + "@esbuild/freebsd-x64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz#37a693553d42ff77cd7126764b535fb6cc28a11c" @@ -761,6 +917,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz#aa5ea58d9c1dd9af688b8b6f63ef0d3d60cea53c" integrity sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw== +"@esbuild/linux-arm64@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.6.tgz#967dfb951c6b2de6f2af82e96e25d63747f75079" + integrity sha512-bUR58IFOMJX523aDVozswnlp5yry7+0cRLCXDsxnUeQYJik1DukMY+apBsLOZJblpH+K7ox7YrKrHmJoWqVR9w== + "@esbuild/linux-arm64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz#be9b145985ec6c57470e0e051d887b09dddb2d4b" @@ -771,6 +932,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz#055b63725df678379b0f6db9d0fa85463755b2e5" integrity sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A== +"@esbuild/linux-arm@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.6.tgz#097a0ee2be39fed3f37ea0e587052961e3bcc110" + integrity sha512-7YdGiurNt7lqO0Bf/U9/arrPWPqdPqcV6JCZda4LZgEn+PTQ5SMEI4MGR52Bfn3+d6bNEGcWFzlIxiQdS48YUw== + "@esbuild/linux-arm@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz#207ecd982a8db95f7b5279207d0ff2331acf5eef" @@ -781,6 +947,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz#76b3b98cb1f87936fbc37f073efabad49dcd889c" integrity sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg== +"@esbuild/linux-ia32@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.6.tgz#a38a789d0ed157495a6b5b4469ec7868b59e5278" + integrity sha512-ujp8uoQCM9FRcbDfkqECoARsLnLfCUhKARTP56TFPog8ie9JG83D5GVKjQ6yVrEVdMie1djH86fm98eY3quQkQ== + "@esbuild/linux-ia32@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz#d0d86b5ca1562523dc284a6723293a52d5860601" @@ -791,6 +962,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz#c0e5e787c285264e5dfc7a79f04b8b4eefdad7fa" integrity sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig== +"@esbuild/linux-loong64@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.6.tgz#ae3983d0fb4057883c8246f57d2518c2af7cf2ad" + integrity sha512-y2NX1+X/Nt+izj9bLoiaYB9YXT/LoaQFYvCkVD77G/4F+/yuVXYCWz4SE9yr5CBMbOxOfBcy/xFL4LlOeNlzYQ== + "@esbuild/linux-loong64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz#9a37f87fec4b8408e682b528391fa22afd952299" @@ -801,6 +977,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz#a6184e62bd7cdc63e0c0448b83801001653219c5" integrity sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ== +"@esbuild/linux-mips64el@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.6.tgz#15fbbe04648d944ec660ee5797febdf09a9bd6af" + integrity sha512-09AXKB1HDOzXD+j3FdXCiL/MWmZP0Ex9eR8DLMBVcHorrWJxWmY8Nms2Nm41iRM64WVx7bA/JVHMv081iP2kUA== + "@esbuild/linux-mips64el@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz#4ddebd4e6eeba20b509d8e74c8e30d8ace0b89ec" @@ -811,6 +992,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz#d08e39ce86f45ef8fc88549d29c62b8acf5649aa" integrity sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA== +"@esbuild/linux-ppc64@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.6.tgz#38210094e8e1a971f2d1fd8e48462cc65f15ef19" + integrity sha512-AmLhMzkM8JuqTIOhxnX4ubh0XWJIznEynRnZAVdA2mMKE6FAfwT2TWKTwdqMG+qEaeyDPtfNoZRpJbD4ZBv0Tg== + "@esbuild/linux-ppc64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz#adb67dadb73656849f63cd522f5ecb351dd8dee8" @@ -821,6 +1007,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz#8d252f0b7756ffd6d1cbde5ea67ff8fd20437f20" integrity sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg== +"@esbuild/linux-riscv64@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.6.tgz#bc3c66d5578c3b9951a6ed68763f2a6856827e4a" + integrity sha512-Y4Ri62PfavhLQhFbqucysHOmRamlTVK10zPWlqjNbj2XMea+BOs4w6ASKwQwAiqf9ZqcY9Ab7NOU4wIgpxwoSQ== + "@esbuild/linux-riscv64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz#11bc0698bf0a2abf8727f1c7ace2112612c15adf" @@ -831,6 +1022,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz#19f6dcdb14409dae607f66ca1181dd4e9db81300" integrity sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg== +"@esbuild/linux-s390x@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.6.tgz#d7ba7af59285f63cfce6e5b7f82a946f3e6d67fc" + integrity sha512-SPUiz4fDbnNEm3JSdUW8pBJ/vkop3M1YwZAVwvdwlFLoJwKEZ9L98l3tzeyMzq27CyepDQ3Qgoba44StgbiN5Q== + "@esbuild/linux-s390x@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz#e86fb8ffba7c5c92ba91fc3b27ed5a70196c3cc8" @@ -841,6 +1037,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz#3c830c90f1a5d7dd1473d5595ea4ebb920988685" integrity sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ== +"@esbuild/linux-x64@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.6.tgz#ba51f8760a9b9370a2530f98964be5f09d90fed0" + integrity sha512-a3yHLmOodHrzuNgdpB7peFGPx1iJ2x6m+uDvhP2CKdr2CwOaqEFMeSqYAHU7hG+RjCq8r2NFujcd/YsEsFgTGw== + "@esbuild/linux-x64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz#5f37cfdc705aea687dfe5dfbec086a05acfe9c78" @@ -851,6 +1052,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz#86eca35203afc0d9de0694c64ec0ab0a378f6fff" integrity sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw== +"@esbuild/netbsd-x64@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.6.tgz#e84d6b6fdde0261602c1e56edbb9e2cb07c211b9" + integrity sha512-EanJqcU/4uZIBreTrnbnre2DXgXSa+Gjap7ifRfllpmyAU7YMvaXmljdArptTHmjrkkKm9BK6GH5D5Yo+p6y5A== + "@esbuild/netbsd-x64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz#29da566a75324e0d0dd7e47519ba2f7ef168657b" @@ -861,6 +1067,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz#e771c8eb0e0f6e1877ffd4220036b98aed5915e6" integrity sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ== +"@esbuild/openbsd-x64@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.6.tgz#cf4b9fb80ce6d280a673d54a731d9c661f88b083" + integrity sha512-xaxeSunhQRsTNGFanoOkkLtnmMn5QbA0qBhNet/XLVsc+OVkpIWPHcr3zTW2gxVU5YOHFbIHR9ODuaUdNza2Vw== + "@esbuild/openbsd-x64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz#306c0acbdb5a99c95be98bdd1d47c916e7dc3ff0" @@ -871,6 +1082,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz#9a795ae4b4e37e674f0f4d716f3e226dd7c39baf" integrity sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ== +"@esbuild/sunos-x64@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.6.tgz#a6838e246079b24d962b9dcb8d208a3785210a73" + integrity sha512-gnMnMPg5pfMkZvhHee21KbKdc6W3GR8/JuE0Da1kjwpK6oiFU3nqfHuVPgUX2rsOx9N2SadSQTIYV1CIjYG+xw== + "@esbuild/sunos-x64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz#0933eaab9af8b9b2c930236f62aae3fc593faf30" @@ -881,6 +1097,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz#7df23b61a497b8ac189def6e25a95673caedb03f" integrity sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w== +"@esbuild/win32-arm64@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.6.tgz#ace0186e904d109ea4123317a3ba35befe83ac21" + integrity sha512-G95n7vP1UnGJPsVdKXllAJPtqjMvFYbN20e8RK8LVLhlTiSOH1sd7+Gt7rm70xiG+I5tM58nYgwWrLs6I1jHqg== + "@esbuild/win32-arm64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz#773bdbaa1971b36db2f6560088639ccd1e6773ae" @@ -891,6 +1112,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz#f1ae5abf9ca052ae11c1bc806fb4c0f519bacf90" integrity sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ== +"@esbuild/win32-ia32@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.6.tgz#7fb3f6d4143e283a7f7dffc98a6baf31bb365c7e" + integrity sha512-96yEFzLhq5bv9jJo5JhTs1gI+1cKQ83cUpyxHuGqXVwQtY5Eq54ZEsKs8veKtiKwlrNimtckHEkj4mRh4pPjsg== + "@esbuild/win32-ia32@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz#000516cad06354cc84a73f0943a4aa690ef6fd67" @@ -901,6 +1127,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz#241fe62c34d8e8461cd708277813e1d0ba55ce23" integrity sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ== +"@esbuild/win32-x64@0.17.6": + version "0.17.6" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.6.tgz#563ff4277f1230a006472664fa9278a83dd124da" + integrity sha512-n6d8MOyUrNp6G4VSpRcgjs5xj4A91svJSaiwLIDWVWEsZtpN5FA9NlBbZHDmAJc2e8e6SF4tkBD3HAvPF+7igA== + "@esbuild/win32-x64@0.19.12": version "0.19.12" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz#c57c8afbb4054a3ab8317591a0b7320360b444ae" @@ -1027,11 +1258,68 @@ resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.1.tgz#16308cea045f0fc777b6ff20a9f25474dd8293d2" integrity sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q== +"@frames.js/debugger@^": + version "0.1.9" + resolved "https://registry.yarnpkg.com/@frames.js/debugger/-/debugger-0.1.9.tgz#d3d45ec1f565b5facfd87d41eb8c3b8e9e2ad2e1" + integrity sha512-g7019xfCLMNHoTyaI+TY2L0ZxZnZH2DEvZQAlIeMmRHW0zhwXoKrgGa8QmO0MQtcB6XA3smaO4bM/7U0Yij0pA== + dependencies: + "@farcaster/core" "^0.14.7" + "@noble/ed25519" "^2.0.0" + "@radix-ui/react-accordion" "^1.1.2" + "@radix-ui/react-checkbox" "^1.0.4" + "@radix-ui/react-hover-card" "^1.0.7" + "@radix-ui/react-popover" "^1.0.7" + "@radix-ui/react-slot" "^1.0.2" + "@radix-ui/react-switch" "^1.0.3" + "@radix-ui/react-tabs" "^1.0.4" + "@rainbow-me/rainbowkit" "^2.0.2" + "@tanstack/react-query" "^5.22.2" + "@types/node" "^18.17.0" + "@types/react" "^18.2.0" + "@types/react-dom" "^18.2.0" + "@types/yargs" "^17.0.32" + "@xmtp/frames-validator" "^0.5.2" + autoprefixer "^10.0.1" + class-variance-authority "^0.7.0" + clsx "^2.1.0" + eslint "^8.56.0" + eslint-config-next "^14.1.0" + frames.js "^0.9.0" + is-port-reachable "^4.0.0" + lucide-react "^0.344.0" + next "^14.1.3" + open "^10.0.3" + postcss "^8" + qrcode.react "^3.1.0" + react "^18.2.0" + react-dom "^18.2.0" + tailwind-merge "^2.2.1" + tailwindcss "^3.3.0" + tailwindcss-animate "^1.0.7" + typescript "^5.3.3" + viem "^2.7.12" + wagmi "^2.5.7" + yargs "^17.7.2" + "@hono/node-server@^1.2.3": version "1.8.2" resolved "https://registry.yarnpkg.com/@hono/node-server/-/node-server-1.8.2.tgz#940b3a0dbd7adbc510b79b626f3603258493354b" integrity sha512-h8l2TBLCPHZBUrrkosZ6L5CpBLj6zdESyF4B+zngiCDF7aZFQJ0alVbLx7jn8PCVi9EyoFf8a4hOZFi1tD95EA== +"@hono/node-server@^1.8.2", "@hono/node-server@^1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@hono/node-server/-/node-server-1.9.0.tgz#b3f0fb41e40bbc46c9e940f43d6c917455eaeb59" + integrity sha512-oJjk7WXBlENeHhWiMqSyxPIZ3Kmf5ZYxqdlcSIXyN8Rn50bNJsPl99G4POBS03Jxh56FdfRJ0SEnC8mAVIiavQ== + +"@hono/vite-dev-server@^0.10.0": + version "0.10.0" + resolved "https://registry.yarnpkg.com/@hono/vite-dev-server/-/vite-dev-server-0.10.0.tgz#0e79ab02132cac4ffb62b6ca029d11bad8f0a0bb" + integrity sha512-JWqdgH59x/PKDrwVCS5EW4eOL4fV+JOuzlKgaHk5eQUgE9vkPwyWwmf8f8rXjsXt5zxOKS3XMlf8sZeglFg3hw== + dependencies: + "@hono/node-server" "^1.8.2" + miniflare "^3.20231218.2" + minimatch "^9.0.3" + "@humanwhocodes/config-array@^0.11.14": version "0.11.14" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" @@ -1287,7 +1575,7 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.24" -"@jridgewell/resolve-uri@^3.1.0": +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": version "3.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== @@ -1302,6 +1590,14 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": version "0.3.25" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" @@ -1310,6 +1606,11 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@jspm/core@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@jspm/core/-/core-2.0.1.tgz#3f08c59c60a5f5e994523ed6b0b665ec80adc94e" + integrity sha512-Lg3PnLp0QXpxwLIAuuJboLeRaIhrgJjeuh797QADg3xz8wGLugQOS5DpsE8A6i6Adgzf+bacllkKZG3J0tGfDw== + "@lit-labs/ssr-dom-shim@^1.0.0", "@lit-labs/ssr-dom-shim@^1.1.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.0.tgz#353ce4a76c83fadec272ea5674ede767650762fd" @@ -1344,6 +1645,29 @@ globby "^11.0.0" read-yaml-file "^1.1.0" +"@mdx-js/mdx@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-2.3.0.tgz#d65d8c3c28f3f46bb0e7cb3bf7613b39980671a9" + integrity sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA== + dependencies: + "@types/estree-jsx" "^1.0.0" + "@types/mdx" "^2.0.0" + estree-util-build-jsx "^2.0.0" + estree-util-is-identifier-name "^2.0.0" + estree-util-to-js "^1.1.0" + estree-walker "^3.0.0" + hast-util-to-estree "^2.0.0" + markdown-extensions "^1.0.0" + periscopic "^3.0.0" + remark-mdx "^2.0.0" + remark-parse "^10.0.0" + remark-rehype "^10.0.0" + unified "^10.0.0" + unist-util-position-from-estree "^1.0.0" + unist-util-stringify-position "^3.0.0" + unist-util-visit "^4.0.0" + vfile "^5.0.0" + "@mdx-js/mdx@^3.0.0": version "3.0.1" resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-3.0.1.tgz#617bd2629ae561fdca1bb88e3badd947f5a82191" @@ -1636,23 +1960,11 @@ "@motionone/dom" "^10.16.4" tslib "^2.3.1" -"@next/env@14.1.0": - version "14.1.0" - resolved "https://registry.yarnpkg.com/@next/env/-/env-14.1.0.tgz#43d92ebb53bc0ae43dcc64fb4d418f8f17d7a341" - integrity sha512-Py8zIo+02ht82brwwhTg36iogzFqGLPXlRGKQw5s+qP/kMNc4MAyDeEwBKDijk6zTIbegEgu8Qy7C1LboslQAw== - "@next/env@14.1.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/env/-/env-14.1.4.tgz#432e80651733fbd67230bf262aee28be65252674" integrity sha512-e7X7bbn3Z6DWnDi75UWn+REgAbLEqxI8Tq2pkFOFAMpWAWApz/YCUhtWMWn410h8Q2fYiYL7Yg5OlxMOCfFjJQ== -"@next/eslint-plugin-next@14.1.0": - version "14.1.0" - resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-14.1.0.tgz#29b041233fac7417e22eefa4146432d5cd910820" - integrity sha512-x4FavbNEeXx/baD/zC/SdrvkjSby8nBn8KcCREqk6UuwvwoAPZmaV8TFCAuo/cpovBRTIY67mHhe86MQQm/68Q== - dependencies: - glob "10.3.10" - "@next/eslint-plugin-next@14.1.4", "@next/eslint-plugin-next@^14.0.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-14.1.4.tgz#d7372b5ffede0e466af8af2ff534386418827fc8" @@ -1660,91 +1972,46 @@ dependencies: glob "10.3.10" -"@next/swc-darwin-arm64@14.1.0": - version "14.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.0.tgz#70a57c87ab1ae5aa963a3ba0f4e59e18f4ecea39" - integrity sha512-nUDn7TOGcIeyQni6lZHfzNoo9S0euXnu0jhsbMOmMJUBfgsnESdjN97kM7cBqQxZa8L/bM9om/S5/1dzCrW6wQ== - "@next/swc-darwin-arm64@14.1.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.4.tgz#a3bca0dc4393ac4cf3169bbf24df63441de66bb7" integrity sha512-ubmUkbmW65nIAOmoxT1IROZdmmJMmdYvXIe8211send9ZYJu+SqxSnJM4TrPj9wmL6g9Atvj0S/2cFmMSS99jg== -"@next/swc-darwin-x64@14.1.0": - version "14.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.0.tgz#0863a22feae1540e83c249384b539069fef054e9" - integrity sha512-1jgudN5haWxiAl3O1ljUS2GfupPmcftu2RYJqZiMJmmbBT5M1XDffjUtRUzP4W3cBHsrvkfOFdQ71hAreNQP6g== - "@next/swc-darwin-x64@14.1.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.4.tgz#ba3683d4e2d30099f3f2864dd7349a4d9f440140" integrity sha512-b0Xo1ELj3u7IkZWAKcJPJEhBop117U78l70nfoQGo4xUSvv0PJSTaV4U9xQBLvZlnjsYkc8RwQN1HoH/oQmLlQ== -"@next/swc-linux-arm64-gnu@14.1.0": - version "14.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.0.tgz#893da533d3fce4aec7116fe772d4f9b95232423c" - integrity sha512-RHo7Tcj+jllXUbK7xk2NyIDod3YcCPDZxj1WLIYxd709BQ7WuRYl3OWUNG+WUfqeQBds6kvZYlc42NJJTNi4tQ== - "@next/swc-linux-arm64-gnu@14.1.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.4.tgz#3519969293f16379954b7e196deb0c1eecbb2f8b" integrity sha512-457G0hcLrdYA/u1O2XkRMsDKId5VKe3uKPvrKVOyuARa6nXrdhJOOYU9hkKKyQTMru1B8qEP78IAhf/1XnVqKA== -"@next/swc-linux-arm64-musl@14.1.0": - version "14.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.0.tgz#d81ddcf95916310b8b0e4ad32b637406564244c0" - integrity sha512-v6kP8sHYxjO8RwHmWMJSq7VZP2nYCkRVQ0qolh2l6xroe9QjbgV8siTbduED4u0hlk0+tjS6/Tuy4n5XCp+l6g== - "@next/swc-linux-arm64-musl@14.1.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.4.tgz#4bb3196bd402b3f84cf5373ff1021f547264d62f" integrity sha512-l/kMG+z6MB+fKA9KdtyprkTQ1ihlJcBh66cf0HvqGP+rXBbOXX0dpJatjZbHeunvEHoBBS69GYQG5ry78JMy3g== -"@next/swc-linux-x64-gnu@14.1.0": - version "14.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.0.tgz#18967f100ec19938354332dcb0268393cbacf581" - integrity sha512-zJ2pnoFYB1F4vmEVlb/eSe+VH679zT1VdXlZKX+pE66grOgjmKJHKacf82g/sWE4MQ4Rk2FMBCRnX+l6/TVYzQ== - "@next/swc-linux-x64-gnu@14.1.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.4.tgz#1b3372c98c83dcdab946cdb4ee06e068b8139ba3" integrity sha512-BapIFZ3ZRnvQ1uWbmqEGJuPT9cgLwvKtxhK/L2t4QYO7l+/DxXuIGjvp1x8rvfa/x1FFSsipERZK70pewbtJtw== -"@next/swc-linux-x64-musl@14.1.0": - version "14.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.0.tgz#77077cd4ba8dda8f349dc7ceb6230e68ee3293cf" - integrity sha512-rbaIYFt2X9YZBSbH/CwGAjbBG2/MrACCVu2X0+kSykHzHnYH5FjHxwXLkcoJ10cX0aWCEynpu+rP76x0914atg== - "@next/swc-linux-x64-musl@14.1.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.4.tgz#8459088bdc872648ff78f121db596f2533df5808" integrity sha512-mqVxTwk4XuBl49qn2A5UmzFImoL1iLm0KQQwtdRJRKl21ylQwwGCxJtIYo2rbfkZHoSKlh/YgztY0qH3wG1xIg== -"@next/swc-win32-arm64-msvc@14.1.0": - version "14.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.0.tgz#5f0b8cf955644104621e6d7cc923cad3a4c5365a" - integrity sha512-o1N5TsYc8f/HpGt39OUQpQ9AKIGApd3QLueu7hXk//2xq5Z9OxmV6sQfNp8C7qYmiOlHYODOGqNNa0e9jvchGQ== - "@next/swc-win32-arm64-msvc@14.1.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.4.tgz#84280a08c00cc3be24ddd3a12f4617b108e6dea6" integrity sha512-xzxF4ErcumXjO2Pvg/wVGrtr9QQJLk3IyQX1ddAC/fi6/5jZCZ9xpuL9Tzc4KPWMFq8GGWFVDMshZOdHGdkvag== -"@next/swc-win32-ia32-msvc@14.1.0": - version "14.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.0.tgz#21f4de1293ac5e5a168a412b139db5d3420a89d0" - integrity sha512-XXIuB1DBRCFwNO6EEzCTMHT5pauwaSj4SWs7CYnME57eaReAKBXCnkUE80p/pAZcewm7hs+vGvNqDPacEXHVkw== - "@next/swc-win32-ia32-msvc@14.1.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.4.tgz#23ff7f4bd0a27177428669ef6fa5c3923c738031" integrity sha512-WZiz8OdbkpRw6/IU/lredZWKKZopUMhcI2F+XiMAcPja0uZYdMTZQRoQ0WZcvinn9xZAidimE7tN9W5v9Yyfyw== -"@next/swc-win32-x64-msvc@14.1.0": - version "14.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.0.tgz#e561fb330466d41807123d932b365cf3d33ceba2" - integrity sha512-9WEbVRRAqJ3YFVqEZIxUqkiO8l1nool1LmNxygr5HWF8AcSYsEpneUDhmjUVJEzO2A04+oPtZdombzzPPkTtgg== - "@next/swc-win32-x64-msvc@14.1.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.4.tgz#bccf5beccfde66d6c66fa4e2509118c796385eda" @@ -1824,6 +2091,47 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@npmcli/fs@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-3.1.0.tgz#233d43a25a91d68c3a863ba0da6a3f00924a173e" + integrity sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w== + dependencies: + semver "^7.3.5" + +"@npmcli/git@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@npmcli/git/-/git-4.1.0.tgz#ab0ad3fd82bc4d8c1351b6c62f0fa56e8fe6afa6" + integrity sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ== + dependencies: + "@npmcli/promise-spawn" "^6.0.0" + lru-cache "^7.4.4" + npm-pick-manifest "^8.0.0" + proc-log "^3.0.0" + promise-inflight "^1.0.1" + promise-retry "^2.0.1" + semver "^7.3.5" + which "^3.0.0" + +"@npmcli/package-json@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@npmcli/package-json/-/package-json-4.0.1.tgz#1a07bf0e086b640500791f6bf245ff43cc27fa37" + integrity sha512-lRCEGdHZomFsURroh522YvA/2cVb9oPIJrjHanCJZkiasz1BzcnLr3tBJhlV7S86MBJBuAQ33is2D60YitZL2Q== + dependencies: + "@npmcli/git" "^4.1.0" + glob "^10.2.2" + hosted-git-info "^6.1.1" + json-parse-even-better-errors "^3.0.0" + normalize-package-data "^5.0.0" + proc-log "^3.0.0" + semver "^7.5.3" + +"@npmcli/promise-spawn@^6.0.0": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz#c8bc4fa2bd0f01cb979d8798ba038f314cfa70f2" + integrity sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg== + dependencies: + which "^3.0.0" + "@open-frames/proxy-client@^0.2.0": version "0.2.1" resolved "https://registry.yarnpkg.com/@open-frames/proxy-client/-/proxy-client-0.2.1.tgz#876c5a1cdf5acfe85b56d656f4cc73d15c9843a9" @@ -1943,6 +2251,11 @@ resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== +"@polka/url@^1.0.0-next.24": + version "1.0.0-next.25" + resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.25.tgz#f077fdc0b5d0078d30893396ff4827a13f99e817" + integrity sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ== + "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" @@ -2407,7 +2720,73 @@ dependencies: merge-options "^3.0.4" -"@remix-run/node@^2.8.1": +"@remix-run/dev@^2.8.1": + version "2.8.1" + resolved "https://registry.yarnpkg.com/@remix-run/dev/-/dev-2.8.1.tgz#472b411499009e985999cc483e5853127896ed5f" + integrity sha512-qFt4jAsAJeIOyg6ngeSnTG/9Z5N9QJfeThP/8wRHc1crqYgTiEtcI3DZ8WlAXjVSF5emgn/ZZKqzLAI02OgMfQ== + dependencies: + "@babel/core" "^7.21.8" + "@babel/generator" "^7.21.5" + "@babel/parser" "^7.21.8" + "@babel/plugin-syntax-decorators" "^7.22.10" + "@babel/plugin-syntax-jsx" "^7.21.4" + "@babel/preset-typescript" "^7.21.5" + "@babel/traverse" "^7.23.2" + "@babel/types" "^7.22.5" + "@mdx-js/mdx" "^2.3.0" + "@npmcli/package-json" "^4.0.1" + "@remix-run/node" "2.8.1" + "@remix-run/router" "1.15.3-pre.0" + "@remix-run/server-runtime" "2.8.1" + "@types/mdx" "^2.0.5" + "@vanilla-extract/integration" "^6.2.0" + arg "^5.0.1" + cacache "^17.1.3" + chalk "^4.1.2" + chokidar "^3.5.1" + cross-spawn "^7.0.3" + dotenv "^16.0.0" + es-module-lexer "^1.3.1" + esbuild "0.17.6" + esbuild-plugins-node-modules-polyfill "^1.6.0" + execa "5.1.1" + exit-hook "2.2.1" + express "^4.17.1" + fs-extra "^10.0.0" + get-port "^5.1.1" + gunzip-maybe "^1.4.2" + jsesc "3.0.2" + json5 "^2.2.2" + lodash "^4.17.21" + lodash.debounce "^4.0.8" + minimatch "^9.0.0" + ora "^5.4.1" + picocolors "^1.0.0" + picomatch "^2.3.1" + pidtree "^0.6.0" + postcss "^8.4.19" + postcss-discard-duplicates "^5.1.0" + postcss-load-config "^4.0.1" + postcss-modules "^6.0.0" + prettier "^2.7.1" + pretty-ms "^7.0.1" + react-refresh "^0.14.0" + remark-frontmatter "4.0.1" + remark-mdx-frontmatter "^1.0.1" + semver "^7.3.7" + set-cookie-parser "^2.6.0" + tar-fs "^2.1.1" + tsconfig-paths "^4.0.0" + ws "^7.4.5" + +"@remix-run/express@2.8.1": + version "2.8.1" + resolved "https://registry.yarnpkg.com/@remix-run/express/-/express-2.8.1.tgz#d12c94354f8a3a5641c1b6f2f6b915f8dd51bff1" + integrity sha512-p1eo8uwZk8uLihSDpUnPOPsTDfghWikVPQfa+e0ZMk6tnJCjcpHAyENKDFtn9vDh9h7YNUg6A7+19CStHgxd7Q== + dependencies: + "@remix-run/node" "2.8.1" + +"@remix-run/node@2.8.1", "@remix-run/node@^2.8.1": version "2.8.1" resolved "https://registry.yarnpkg.com/@remix-run/node/-/node-2.8.1.tgz#0244ead9a0267663cd394f3d462d4baaccaf5960" integrity sha512-ddCwBVlfLvRxTQJHPcaM1lhfMjsFYG3EGmYpWJIWnnzDX5EbX9pUNHBWisMuH1eA0c7pbw0PbW0UtCttKYx2qg== @@ -2421,11 +2800,40 @@ source-map-support "^0.5.21" stream-slice "^0.1.2" +"@remix-run/react@^2.8.1": + version "2.8.1" + resolved "https://registry.yarnpkg.com/@remix-run/react/-/react-2.8.1.tgz#89d7f6a6a5d706eb93b3bdeb92dcc3e338d7a0b4" + integrity sha512-HTPm1U8+xz2jPaVjZnssrckfmFMA8sUZUdaWnoF5lmLWdReqcQv+XlBhIrQQ3jO9L8iYYdnzaSZZcRFYSdpTYg== + dependencies: + "@remix-run/router" "1.15.3" + "@remix-run/server-runtime" "2.8.1" + react-router "6.22.3" + react-router-dom "6.22.3" + "@remix-run/router@1.15.3": version "1.15.3" resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.15.3.tgz#d2509048d69dbb72d5389a14945339f1430b2d3c" integrity sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w== +"@remix-run/router@1.15.3-pre.0": + version "1.15.3-pre.0" + resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.15.3-pre.0.tgz#a77015ddaafcf0f0df538874f77abdbfcf86cc59" + integrity sha512-JUQb6sztqJpRbsdKpx3D4+6eaGmHU4Yb/QeKrES/ZbLuijlZMOmZ+gV0ohX5vrRDnJHJmcQPq3Tpk0GGPNM9gg== + +"@remix-run/serve@^2.8.1": + version "2.8.1" + resolved "https://registry.yarnpkg.com/@remix-run/serve/-/serve-2.8.1.tgz#b1f58ba2a0b310a1de0e2d6f336135a5a0f9287a" + integrity sha512-PyCV7IMnRshwfFw7JJ2hZJppX88VAhZyYjeTAmYb6PK7IDtdmqUf5eOrYDi8gCu914C+aZRu6blxpLRlpyCY8Q== + dependencies: + "@remix-run/express" "2.8.1" + "@remix-run/node" "2.8.1" + chokidar "^3.5.3" + compression "^1.7.4" + express "^4.17.1" + get-port "5.1.1" + morgan "^1.10.0" + source-map-support "^0.5.21" + "@remix-run/server-runtime@2.8.1": version "2.8.1" resolved "https://registry.yarnpkg.com/@remix-run/server-runtime/-/server-runtime-2.8.1.tgz#621f52e271e8ae117e4882761e143fa7ce7f9d42" @@ -2939,7 +3347,7 @@ dependencies: "@types/estree" "*" -"@types/babel__core@^7.1.14", "@types/babel__core@^7.20.4": +"@types/babel__core@^7.1.14", "@types/babel__core@^7.20.4", "@types/babel__core@^7.20.5": version "7.20.5" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== @@ -3081,6 +3489,13 @@ resolved "https://registry.yarnpkg.com/@types/har-format/-/har-format-1.2.15.tgz#f352493638c2f89d706438a19a9eb300b493b506" integrity sha512-RpQH4rXLuvTXKR0zqHq3go0RVXYv/YVqv4TnPH95VbwUxZdQlK1EtcMvQvMpDngHbt13Csh9Z4qT9AbkiQH5BA== +"@types/hast@^2.0.0": + version "2.3.10" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.10.tgz#5c9d9e0b304bbb8879b857225c5ebab2d81d7643" + integrity sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw== + dependencies: + "@types/unist" "^2" + "@types/hast@^3.0.0", "@types/hast@^3.0.4": version "3.0.4" resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.4.tgz#1d6b39993b82cea6ad783945b0508c25903e15aa" @@ -3130,6 +3545,13 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== +"@types/mdast@^3.0.0": + version "3.0.15" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.15.tgz#49c524a263f30ffa28b71ae282f813ed000ab9f5" + integrity sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ== + dependencies: + "@types/unist" "^2" + "@types/mdast@^4.0.0": version "4.0.3" resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-4.0.3.tgz#1e011ff013566e919a4232d1701ad30d70cab333" @@ -3142,6 +3564,11 @@ resolved "https://registry.yarnpkg.com/@types/mdx/-/mdx-2.0.11.tgz#21f4c166ed0e0a3a733869ba04cd8daea9834b8e" integrity sha512-HM5bwOaIQJIQbAYfax35HCKxx7a3KrK3nBtIqJgSOitivTD1y3oW9P3rxY9RkXYPUk7y/AjAohfHKmFpGE79zw== +"@types/mdx@^2.0.5": + version "2.0.12" + resolved "https://registry.yarnpkg.com/@types/mdx/-/mdx-2.0.12.tgz#38db34cc8999b982beaec01399620bee6c65ef2e" + integrity sha512-H9VZ9YqE+H28FQVchC83RCs5xQ2J7mAAv6qdDEaWmXEVl3OpdH+xfrSUzQ1lp7U7oSTRZ0RvW08ASPJsYBi7Cw== + "@types/methods@^1.1.4": version "1.1.4" resolved "https://registry.yarnpkg.com/@types/methods/-/methods-1.1.4.tgz#d3b7ac30ac47c91054ea951ce9eed07b1051e547" @@ -3211,7 +3638,7 @@ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== -"@types/react-dom@^18.2.0", "@types/react-dom@^18.2.18": +"@types/react-dom@^18.2.0", "@types/react-dom@^18.2.18", "@types/react-dom@^18.2.7": version "18.2.22" resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.22.tgz#d332febf0815403de6da8a97e5fe282cbe609bae" integrity sha512-fHkBXPeNtfvri6gdsMYyW+dW7RXFo6Ad09nLFK0VQWR7yGLai/Cyvyj696gbwYvBnhGtevUG9cET0pmUbMtoPQ== @@ -3227,6 +3654,15 @@ "@types/scheduler" "*" csstype "^3.0.2" +"@types/react@^18.2.20", "@types/react@^18.2.45": + version "18.2.70" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.70.tgz#89a37f9e0a6a4931f4259c598f40fd44dd6abf71" + integrity sha512-hjlM2hho2vqklPhopNkXkdkeq6Lv8WSZTpr7956zY+3WS5cfYUewtCzsJLsbW5dEv3lfSeQ4W14ZFeKC437JRQ== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + "@types/scheduler@*": version "0.16.8" resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.8.tgz#ce5ace04cfeabe7ef87c0091e50752e36707deff" @@ -3293,7 +3729,7 @@ resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.2.tgz#6dd61e43ef60b34086287f83683a5c1b2dc53d20" integrity sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ== -"@types/unist@^2.0.0": +"@types/unist@^2", "@types/unist@^2.0.0": version "2.0.10" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.10.tgz#04ffa7f406ab628f7f7e97ca23e290cd8ab15efc" integrity sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA== @@ -3310,7 +3746,7 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^6.17.0", "@typescript-eslint/eslint-plugin@^6.5.0": +"@typescript-eslint/eslint-plugin@^6.17.0", "@typescript-eslint/eslint-plugin@^6.5.0", "@typescript-eslint/eslint-plugin@^6.7.4": version "6.21.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz#30830c1ca81fd5f3c2714e524c4303e0194f9cd3" integrity sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA== @@ -3327,7 +3763,7 @@ semver "^7.5.4" ts-api-utils "^1.0.1" -"@typescript-eslint/parser@^5.4.2 || ^6.0.0", "@typescript-eslint/parser@^6.17.0", "@typescript-eslint/parser@^6.5.0": +"@typescript-eslint/parser@^5.4.2 || ^6.0.0", "@typescript-eslint/parser@^6.17.0", "@typescript-eslint/parser@^6.5.0", "@typescript-eslint/parser@^6.7.4": version "6.21.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.21.0.tgz#af8fcf66feee2edc86bc5d1cf45e33b0630bf35b" integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ== @@ -3511,7 +3947,7 @@ dependencies: "@vanilla-extract/private" "^1.0.3" -"@vanilla-extract/integration@^6.3.0": +"@vanilla-extract/integration@^6.2.0", "@vanilla-extract/integration@^6.3.0": version "6.5.0" resolved "https://registry.yarnpkg.com/@vanilla-extract/integration/-/integration-6.5.0.tgz#613407565b07dc60b123ca9080ea3f47cd2ce7bb" integrity sha512-E2YcfO8vA+vs+ua+gpvy1HRqvgWbI+MTlUpxA8FvatOvybuNcWAY0CKwQ/Gpj7rswYKtC6C7+xw33emM6/ImdQ== @@ -3602,6 +4038,17 @@ "@types/babel__core" "^7.20.4" react-refresh "^0.14.0" +"@vitejs/plugin-react@^4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz#744d8e4fcb120fc3dbaa471dadd3483f5a304bb9" + integrity sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ== + dependencies: + "@babel/core" "^7.23.5" + "@babel/plugin-transform-react-jsx-self" "^7.23.3" + "@babel/plugin-transform-react-jsx-source" "^7.23.3" + "@types/babel__core" "^7.20.5" + react-refresh "^0.14.0" + "@wagmi/connectors@4.1.18": version "4.1.18" resolved "https://registry.yarnpkg.com/@wagmi/connectors/-/connectors-4.1.18.tgz#b95350ff2cb527093ff9dd11d382e0563ec546e3" @@ -3973,11 +4420,24 @@ acorn-jsx@^5.0.0, acorn-jsx@^5.3.2: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.0.0, acorn@^8.11.3, acorn@^8.9.0: +acorn-walk@^8.2.0: + version "8.3.2" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" + integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== + +acorn@^8.0.0, acorn@^8.11.3, acorn@^8.8.0, acorn@^8.9.0: version "8.11.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + ajv@^6.12.4, ajv@~6.12.6: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -4047,7 +4507,7 @@ anymatch@^3.0.3, anymatch@^3.1.3, anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" -arg@^5.0.2: +arg@^5.0.1, arg@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== @@ -4192,6 +4652,13 @@ arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== +as-table@^1.0.36: + version "1.0.55" + resolved "https://registry.yarnpkg.com/as-table/-/as-table-1.0.55.tgz#dc984da3937745de902cea1d45843c01bdbbec4f" + integrity sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ== + dependencies: + printable-characters "^1.0.42" + asap@^2.0.0: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" @@ -4356,6 +4823,13 @@ base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +basic-auth@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" + integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg== + dependencies: + safe-buffer "5.1.2" + bcp-47-match@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/bcp-47-match/-/bcp-47-match-2.0.3.tgz#603226f6e5d3914a581408be33b28a53144b09d0" @@ -4373,6 +4847,15 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== +bl@^4.0.3, bl@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + bl@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/bl/-/bl-5.1.0.tgz#183715f678c7188ecef9fe475d90209400624273" @@ -4454,6 +4937,13 @@ brorand@^1.1.0: resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== +browserify-zlib@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d" + integrity sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ== + dependencies: + pako "~0.2.0" + browserslist@^4.22.2, browserslist@^4.23.0: version "4.23.0" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" @@ -4483,6 +4973,14 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + buffer@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" @@ -4503,6 +5001,13 @@ builtin-modules@^3.3.0: resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== +builtins@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/builtins/-/builtins-5.0.1.tgz#87f6db9ab0458be728564fa81d876d8d74552fa9" + integrity sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ== + dependencies: + semver "^7.0.0" + bundle-name@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-4.1.0.tgz#f3b96b34160d6431a19d7688135af7cfb8797889" @@ -4539,6 +5044,24 @@ cac@^6.7.12, cac@^6.7.14: resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== +cacache@^17.1.3: + version "17.1.4" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-17.1.4.tgz#b3ff381580b47e85c6e64f801101508e26604b35" + integrity sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A== + dependencies: + "@npmcli/fs" "^3.1.0" + fs-minipass "^3.0.0" + glob "^10.2.2" + lru-cache "^7.7.1" + minipass "^7.0.3" + minipass-collect "^1.0.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + p-map "^4.0.0" + ssri "^10.0.0" + tar "^6.1.11" + unique-filename "^3.0.0" + call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" @@ -4589,6 +5112,14 @@ caniuse-lite@^1.0.30001579, caniuse-lite@^1.0.30001587, caniuse-lite@^1.0.300015 resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001599.tgz#571cf4f3f1506df9bf41fcbb6d10d5d017817bce" integrity sha512-LRAQHZ4yT1+f9LemSMeqdMpMxZcc4RMWdj4tiFe3G8tNkWK+E58g+/tzotb5cU6TbcVJLr4fySiAW7XmxQvZQA== +capnp-ts@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/capnp-ts/-/capnp-ts-0.7.0.tgz#16fd8e76b667d002af8fcf4bf92bf15d1a7b54a9" + integrity sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g== + dependencies: + debug "^4.3.1" + tslib "^2.2.0" + ccount@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5" @@ -4603,7 +5134,7 @@ chalk@^2.1.0, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0, chalk@^4.1.1, chalk@^4.1.2: +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -4686,6 +5217,16 @@ chokidar@^3.5.1, chokidar@^3.5.3, chokidar@^3.6.0: optionalDependencies: fsevents "~2.3.2" +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + chroma-js@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chroma-js/-/chroma-js-2.4.2.tgz#dffc214ed0c11fa8eefca2c36651d8e57cbfb2b0" @@ -4722,6 +5263,18 @@ clean-regexp@^1.0.0: dependencies: escape-string-regexp "^1.0.5" +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + cli-cursor@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-4.0.0.tgz#3cecfe3734bf4fe02a8361cbdc0f6fe28c6a57ea" @@ -4729,7 +5282,7 @@ cli-cursor@^4.0.0: dependencies: restore-cursor "^4.0.0" -cli-spinners@^2.9.0: +cli-spinners@^2.5.0, cli-spinners@^2.9.0: version "2.9.2" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== @@ -4934,6 +5487,11 @@ cookie@0.6.0, cookie@^0.6.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== +cookie@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + cookiejar@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b" @@ -4984,6 +5542,13 @@ create-vocs@^1.0.0-alpha.4: fs-extra "^11.1.1" picocolors "^1.0.0" +cross-env@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== + dependencies: + cross-spawn "^7.0.1" + cross-fetch@^3.1.4, cross-fetch@^3.1.5: version "3.1.8" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" @@ -5007,7 +5572,7 @@ cross-spawn@^5.1.0: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -5111,6 +5676,11 @@ damerau-levenshtein@^1.0.8: resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== +data-uri-to-buffer@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz#d296973d5a4897a5dbe31716d118211921f04770" + integrity sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA== + data-uri-to-buffer@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636" @@ -5274,7 +5844,7 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== -depd@2.0.0: +depd@2.0.0, depd@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== @@ -5361,6 +5931,11 @@ diff-sequences@^29.6.3: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== +diff@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" + integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== + dijkstrajs@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.3.tgz#4c8dbdea1f0f6478bff94d9c49c784d623e4fc23" @@ -5432,11 +6007,21 @@ dotenv@16.0.3: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== -dotenv@^16.4.5: +dotenv@^16.0.0, dotenv@^16.4.5: version "16.4.5" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== +duplexify@^3.5.0, duplexify@^3.6.0: + version "3.7.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" + integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + duplexify@^4.1.2: version "4.1.3" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.3.tgz#a07e1c0d0a2c001158563d32592ba58bddb0236f" @@ -5514,7 +6099,7 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== -end-of-stream@^1.1.0, end-of-stream@^1.4.0, end-of-stream@^1.4.1, end-of-stream@^1.4.4: +end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.0, end-of-stream@^1.4.1, end-of-stream@^1.4.4: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -5558,6 +6143,11 @@ entities@^4.2.0, entities@^4.4.0: resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== +err-code@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" + integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== + error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -5696,6 +6286,11 @@ es-iterator-helpers@^1.0.15, es-iterator-helpers@^1.0.17: iterator.prototype "^1.1.2" safe-array-concat "^1.1.2" +es-module-lexer@^1.3.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.4.2.tgz#ba1a62255ff9b41023aaf9bd08c016a5f1a3fef3" + integrity sha512-7nOqkomXZEaxUDJw21XZNtRk739QvrPSoZoRtbsEfcii00vdzZUh6zh1CQwHhrib8MdEtJfv5rJiGeb4KuV/vw== + es-object-atoms@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" @@ -5728,6 +6323,43 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +esbuild-plugins-node-modules-polyfill@^1.6.0: + version "1.6.3" + resolved "https://registry.yarnpkg.com/esbuild-plugins-node-modules-polyfill/-/esbuild-plugins-node-modules-polyfill-1.6.3.tgz#8090fc4126b3d6a604ec01fd4646f407059301cf" + integrity sha512-nydQGT3RijD8mBd3Hek+2gSAxndgceZU9GIjYYiqU+7CE7veN8utTmupf0frcKpwIXCXWpRofL9CY9k0yU70CA== + dependencies: + "@jspm/core" "^2.0.1" + local-pkg "^0.5.0" + resolve.exports "^2.0.2" + +esbuild@0.17.6: + version "0.17.6" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.6.tgz#bbccd4433629deb6e0a83860b3b61da120ba4e01" + integrity sha512-TKFRp9TxrJDdRWfSsSERKEovm6v30iHnrjlcGhLBOtReE28Yp1VSBRfO3GTaOFMoxsNerx4TjrhzSuma9ha83Q== + optionalDependencies: + "@esbuild/android-arm" "0.17.6" + "@esbuild/android-arm64" "0.17.6" + "@esbuild/android-x64" "0.17.6" + "@esbuild/darwin-arm64" "0.17.6" + "@esbuild/darwin-x64" "0.17.6" + "@esbuild/freebsd-arm64" "0.17.6" + "@esbuild/freebsd-x64" "0.17.6" + "@esbuild/linux-arm" "0.17.6" + "@esbuild/linux-arm64" "0.17.6" + "@esbuild/linux-ia32" "0.17.6" + "@esbuild/linux-loong64" "0.17.6" + "@esbuild/linux-mips64el" "0.17.6" + "@esbuild/linux-ppc64" "0.17.6" + "@esbuild/linux-riscv64" "0.17.6" + "@esbuild/linux-s390x" "0.17.6" + "@esbuild/linux-x64" "0.17.6" + "@esbuild/netbsd-x64" "0.17.6" + "@esbuild/openbsd-x64" "0.17.6" + "@esbuild/sunos-x64" "0.17.6" + "@esbuild/win32-arm64" "0.17.6" + "@esbuild/win32-ia32" "0.17.6" + "@esbuild/win32-x64" "0.17.6" + esbuild@^0.19.2, "esbuild@npm:esbuild@~0.17.6 || ~0.18.0 || ~0.19.0": version "0.19.12" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.12.tgz#dc82ee5dc79e82f5a5c3b4323a2a641827db3e04" @@ -5816,21 +6448,6 @@ escape-string-regexp@^5.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== -eslint-config-next@14.1.0: - version "14.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-14.1.0.tgz#7e309d426b8afacaba3b32fdbb02ba220b6d0a97" - integrity sha512-SBX2ed7DoRFXC6CQSLc/SbLY9Ut6HxNB2wPTcoIWjUMd7aF7O/SIE7111L8FdZ9TXsNV4pulUDnfthpyPtbFUg== - dependencies: - "@next/eslint-plugin-next" "14.1.0" - "@rushstack/eslint-patch" "^1.3.3" - "@typescript-eslint/parser" "^5.4.2 || ^6.0.0" - eslint-import-resolver-node "^0.3.6" - eslint-import-resolver-typescript "^3.5.2" - eslint-plugin-import "^2.28.1" - eslint-plugin-jsx-a11y "^6.7.1" - eslint-plugin-react "^7.33.2" - eslint-plugin-react-hooks "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" - eslint-config-next@^14.1.0: version "14.1.4" resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-14.1.4.tgz#22f2ba4c0993e991249d863656a64c204bae542c" @@ -6142,6 +6759,13 @@ estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== +estree-util-attach-comments@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/estree-util-attach-comments/-/estree-util-attach-comments-2.1.1.tgz#ee44f4ff6890ee7dfb3237ac7810154c94c63f84" + integrity sha512-+5Ba/xGGS6mnwFbXIuQiDPTbuTxuMCooq3arVv7gPZtYpjp+VXH/NkHAP35OOefPhNG/UGqU3vt/LTABwcHX0w== + dependencies: + "@types/estree" "^1.0.0" + estree-util-attach-comments@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz#344bde6a64c8a31d15231e5ee9e297566a691c2d" @@ -6149,6 +6773,15 @@ estree-util-attach-comments@^3.0.0: dependencies: "@types/estree" "^1.0.0" +estree-util-build-jsx@^2.0.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/estree-util-build-jsx/-/estree-util-build-jsx-2.2.2.tgz#32f8a239fb40dc3f3dca75bb5dcf77a831e4e47b" + integrity sha512-m56vOXcOBuaF+Igpb9OPAy7f9w9OIkb5yhjsZuaPm7HoGi4oTOQi0h2+yZ+AtKklYFZ+rPC4n0wYCJCEU1ONqg== + dependencies: + "@types/estree-jsx" "^1.0.0" + estree-util-is-identifier-name "^2.0.0" + estree-walker "^3.0.0" + estree-util-build-jsx@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz#b6d0bced1dcc4f06f25cf0ceda2b2dcaf98168f1" @@ -6159,11 +6792,30 @@ estree-util-build-jsx@^3.0.0: estree-util-is-identifier-name "^3.0.0" estree-walker "^3.0.0" -estree-util-is-identifier-name@^3.0.0: - version "3.0.0" +estree-util-is-identifier-name@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/estree-util-is-identifier-name/-/estree-util-is-identifier-name-1.1.0.tgz#2e3488ea06d9ea2face116058864f6370b37456d" + integrity sha512-OVJZ3fGGt9By77Ix9NhaRbzfbDV/2rx9EP7YIDJTmsZSEc5kYn2vWcNccYyahJL2uAQZK2a5Or2i0wtIKTPoRQ== + +estree-util-is-identifier-name@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/estree-util-is-identifier-name/-/estree-util-is-identifier-name-2.1.0.tgz#fb70a432dcb19045e77b05c8e732f1364b4b49b2" + integrity sha512-bEN9VHRyXAUOjkKVQVvArFym08BTWB0aJPppZZr0UNyAqWsLaVfAqP7hbaTJjzHifmB5ebnR8Wm7r7yGN/HonQ== + +estree-util-is-identifier-name@^3.0.0: + version "3.0.0" resolved "https://registry.yarnpkg.com/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz#0b5ef4c4ff13508b34dcd01ecfa945f61fce5dbd" integrity sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg== +estree-util-to-js@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/estree-util-to-js/-/estree-util-to-js-1.2.0.tgz#0f80d42443e3b13bd32f7012fffa6f93603f4a36" + integrity sha512-IzU74r1PK5IMMGZXUVZbmiu4A1uhiPgW5hm1GjcOfr4ZzHaMPpLNJjR7HjXiIOzi25nZDrgFTobHTkV5Q6ITjA== + dependencies: + "@types/estree-jsx" "^1.0.0" + astring "^1.8.0" + source-map "^0.7.0" + estree-util-to-js@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz#10a6fb924814e6abb62becf0d2bc4dea51d04f17" @@ -6173,6 +6825,13 @@ estree-util-to-js@^2.0.0: astring "^1.8.0" source-map "^0.7.0" +estree-util-value-to-estree@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/estree-util-value-to-estree/-/estree-util-value-to-estree-1.3.0.tgz#1d3125594b4d6680f666644491e7ac1745a3df49" + integrity sha512-Y+ughcF9jSUJvncXwqRageavjrNPAI+1M/L3BI3PyLp1nmgYTGUXU6t5z1Y7OWuThoDdhPME07bQU+d5LxdJqw== + dependencies: + is-plain-obj "^3.0.0" + estree-util-value-to-estree@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/estree-util-value-to-estree/-/estree-util-value-to-estree-3.0.1.tgz#0b7b5d6b6a4aaad5c60999ffbc265a985df98ac5" @@ -6181,6 +6840,14 @@ estree-util-value-to-estree@^3.0.0: "@types/estree" "^1.0.0" is-plain-obj "^4.0.0" +estree-util-visit@^1.0.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/estree-util-visit/-/estree-util-visit-1.2.1.tgz#8bc2bc09f25b00827294703835aabee1cc9ec69d" + integrity sha512-xbgqcrkIVbIG+lI/gzbvd9SGTJL4zqJKBFttUl5pP27KhAjtMKbX/mQXJ7qgyXpMgVy/zvpm0xoQQaGL8OloOw== + dependencies: + "@types/estree-jsx" "^1.0.0" + "@types/unist" "^2.0.0" + estree-util-visit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/estree-util-visit/-/estree-util-visit-2.0.0.tgz#13a9a9f40ff50ed0c022f831ddf4b58d05446feb" @@ -6286,7 +6953,7 @@ events@^3.3.0: resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== -execa@^5.0.0, execa@^5.1.1: +execa@5.1.1, execa@^5.0.0, execa@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== @@ -6316,6 +6983,11 @@ execa@^8.0.1: signal-exit "^4.1.0" strip-final-newline "^3.0.0" +exit-hook@2.2.1, exit-hook@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-2.2.1.tgz#007b2d92c6428eda2b76e7016a34351586934593" + integrity sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw== + exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -6332,7 +7004,7 @@ expect@^29.0.0, expect@^29.7.0: jest-message-util "^29.7.0" jest-util "^29.7.0" -express@^4.19.1: +express@^4.17.1, express@^4.19.1: version "4.19.1" resolved "https://registry.yarnpkg.com/express/-/express-4.19.1.tgz#4700635795e911600a45596138cf5b0320e78256" integrity sha512-K4w1/Bp7y8iSiVObmCrtq8Cs79XjJc/RU2YYkZQ7wpUu5ZyZ7MtPHkqoMz4pf+mgXfNvo2qft8D9OnrH2ABk9w== @@ -6586,22 +7258,36 @@ fraction.js@^4.3.7: resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7" integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== -frames.js@^0.8.0: - version "0.8.5" - resolved "https://registry.yarnpkg.com/frames.js/-/frames.js-0.8.5.tgz#826ee2262508b5c87c601e1f1b6d8fb1176d1068" - integrity sha512-J6GASOb4CeTPv8YChKpH9yqzVOyccka8IWzusvrdYkyO88so/78LR0EqJwC04CYKwycaIo7JfpNmVIvO8HYf/A== +frames.js@^0.9.0, frames.js@^0.9.3, frames.js@^0.9.6: + version "0.9.6" + resolved "https://registry.yarnpkg.com/frames.js/-/frames.js-0.9.6.tgz#dcf68f88a0237451dba11fbebcfd7df5a004c649" + integrity sha512-NtIs9kWdLnXBB3a7IAnYP3Iv4V+x1dHsKEwacVfWVaFd+3jnzBfiIbvo9dnMuYzFOOyaiPWmZYrff0aTygJP7A== dependencies: "@farcaster/core" "^0.14.7" "@vercel/og" "^0.6.2" cheerio "^1.0.0-rc.12" protobufjs "^7.2.6" - viem "^2.7.1" + viem "^2.7.8" fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + +fs-extra@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-extra@^11.1.1: version "11.2.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" @@ -6629,6 +7315,20 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fs-minipass@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-3.0.3.tgz#79a85981c4dc120065e96f62086bf6f9dc26cc54" + integrity sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw== + dependencies: + minipass "^7.0.3" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -6664,6 +7364,13 @@ futoin-hkdf@^1.5.3: resolved "https://registry.yarnpkg.com/futoin-hkdf/-/futoin-hkdf-1.5.3.tgz#6c8024f2e1429da086d4e18289ef2239ad33ee35" integrity sha512-SewY5KdMpaoCeh7jachEWFsh1nNlaDjNHZXWqL5IGwtpEYHTgkr2+AMCgNwKWkcc0wpSYrZfR7he4WdmHFtDxQ== +generic-names@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/generic-names/-/generic-names-4.0.0.tgz#0bd8a2fd23fe8ea16cbd0a279acd69c06933d9a3" + integrity sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A== + dependencies: + loader-utils "^3.2.0" + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -6700,6 +7407,19 @@ get-port-please@^3.1.2: resolved "https://registry.yarnpkg.com/get-port-please/-/get-port-please-3.1.2.tgz#502795e56217128e4183025c89a48c71652f4e49" integrity sha512-Gxc29eLs1fbn6LQ4jSU4vXjlwyZhF5HsGuMAa7gqBP4Rw4yxxltyDUuF5MBclFzDTXO+ACchGQoeela4DSfzdQ== +get-port@5.1.1, get-port@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" + integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ== + +get-source@^2.0.12: + version "2.0.12" + resolved "https://registry.yarnpkg.com/get-source/-/get-source-2.0.12.tgz#0b47d57ea1e53ce0d3a69f4f3d277eb8047da944" + integrity sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w== + dependencies: + data-uri-to-buffer "^2.0.0" + source-map "^0.6.1" + get-stdin@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-9.0.0.tgz#3983ff82e03d56f1b2ea0d3e60325f39d703a575" @@ -6755,7 +7475,12 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob@10.3.10, glob@^10.3.10, glob@^10.3.7: +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +glob@10.3.10, glob@^10.2.2, glob@^10.3.10, glob@^10.3.7: version "10.3.10" resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== @@ -6820,6 +7545,11 @@ globby@^13.1.2, globby@^13.2.2: merge2 "^1.4.1" slash "^4.0.0" +globrex@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098" + integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg== + gopd@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" @@ -6842,6 +7572,18 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +gunzip-maybe@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz#b913564ae3be0eda6f3de36464837a9cd94b98ac" + integrity sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw== + dependencies: + browserify-zlib "^0.1.4" + is-deflate "^1.0.0" + is-gzip "^1.0.0" + peek-stream "^1.1.0" + pumpify "^1.3.3" + through2 "^2.0.3" + h3@^1.10.2, h3@^1.11.1: version "1.11.1" resolved "https://registry.yarnpkg.com/h3/-/h3-1.11.1.tgz#e9414ae6f2a076a345ea07256b320edb29bab9f7" @@ -6975,6 +7717,27 @@ hast-util-select@^6.0.0: unist-util-visit "^5.0.0" zwitch "^2.0.0" +hast-util-to-estree@^2.0.0: + version "2.3.3" + resolved "https://registry.yarnpkg.com/hast-util-to-estree/-/hast-util-to-estree-2.3.3.tgz#da60142ffe19a6296923ec222aba73339c8bf470" + integrity sha512-ihhPIUPxN0v0w6M5+IiAZZrn0LH2uZomeWwhn7uP7avZC6TE7lIiEh2yBMPr5+zi1aUCXq6VoYRgs2Bw9xmycQ== + dependencies: + "@types/estree" "^1.0.0" + "@types/estree-jsx" "^1.0.0" + "@types/hast" "^2.0.0" + "@types/unist" "^2.0.0" + comma-separated-tokens "^2.0.0" + estree-util-attach-comments "^2.0.0" + estree-util-is-identifier-name "^2.0.0" + hast-util-whitespace "^2.0.0" + mdast-util-mdx-expression "^1.0.0" + mdast-util-mdxjs-esm "^1.0.0" + property-information "^6.0.0" + space-separated-tokens "^2.0.0" + style-to-object "^0.4.1" + unist-util-position "^4.0.0" + zwitch "^2.0.0" + hast-util-to-estree@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/hast-util-to-estree/-/hast-util-to-estree-3.1.0.tgz#f2afe5e869ddf0cf690c75f9fc699f3180b51b19" @@ -7025,6 +7788,11 @@ hast-util-to-string@^3.0.0: dependencies: "@types/hast" "^3.0.0" +hast-util-whitespace@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz#0ec64e257e6fc216c7d14c8a1b74d27d650b4557" + integrity sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng== + hast-util-whitespace@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz#7778ed9d3c92dd9e8c5c8f648a49c21fc51cb621" @@ -7089,6 +7857,13 @@ hosted-git-info@^2.1.4: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== +hosted-git-info@^6.0.0, hosted-git-info@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-6.1.1.tgz#629442c7889a69c05de604d52996b74fe6f26d58" + integrity sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w== + dependencies: + lru-cache "^7.5.1" + html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -7163,12 +7938,17 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" +icss-utils@^5.0.0, icss-utils@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" + integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== + idb-keyval@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/idb-keyval/-/idb-keyval-6.2.1.tgz#94516d625346d16f56f3b33855da11bfded2db33" integrity sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg== -ieee754@^1.2.1: +ieee754@^1.1.13, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -7333,7 +8113,7 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.1.0, is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.13.1: +is-core-module@^2.1.0, is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.13.1, is-core-module@^2.8.1: version "2.13.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== @@ -7359,6 +8139,11 @@ is-decimal@^2.0.0: resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-2.0.1.tgz#9469d2dc190d0214fd87d78b78caecc0cc14eef7" integrity sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A== +is-deflate@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-deflate/-/is-deflate-1.0.0.tgz#c862901c3c161fb09dac7cdc7e784f80e98f2f14" + integrity sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ== + is-docker@^2.0.0, is-docker@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" @@ -7405,6 +8190,11 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-gzip@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-gzip/-/is-gzip-1.0.0.tgz#6ca8b07b99c77998025900e555ced8ed80879a83" + integrity sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ== + is-hexadecimal@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz#86b5bf668fca307498d319dfc03289d781a90027" @@ -7417,6 +8207,11 @@ is-inside-container@^1.0.0: dependencies: is-docker "^3.0.0" +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + is-interactive@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-2.0.0.tgz#40c57614593826da1100ade6059778d597f16e90" @@ -7459,6 +8254,11 @@ is-plain-obj@^2.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== +is-plain-obj@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" + integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== + is-plain-obj@^4.0.0, is-plain-obj@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" @@ -7534,6 +8334,11 @@ is-typed-array@^1.1.13, is-typed-array@^1.1.3: dependencies: which-typed-array "^1.1.14" +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + is-unicode-supported@^1.1.0, is-unicode-supported@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz#d824984b616c292a2e198207d4a609983842f714" @@ -7595,6 +8400,11 @@ isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== +isbot@^4.1.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/isbot/-/isbot-4.4.0.tgz#897ce9f2e498de6181027660ca80de8734d1ef81" + integrity sha512-8ZvOWUA68kyJO4hHJdWjyreq7TYNWTS9y15IzeqVdKxR9pPr3P/3r9AHcoIv9M0Rllkao5qWz2v1lmcyKIVCzQ== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -8077,23 +8887,23 @@ js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.6.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^4.1.0: +js-yaml@^4.0.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== dependencies: argparse "^2.0.1" +jsesc@3.0.2, jsesc@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e" + integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g== + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== -jsesc@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e" - integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g== - jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" @@ -8109,6 +8919,11 @@ json-parse-even-better-errors@^2.3.0: resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== +json-parse-even-better-errors@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz#02bb29fb5da90b5444581749c22cedd3597c6cb0" + integrity sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg== + json-rpc-engine@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-6.1.0.tgz#bf5ff7d029e1c1bf20cb6c0e9f348dcd8be5a393" @@ -8153,7 +8968,7 @@ json5@^1.0.2: dependencies: minimist "^1.2.0" -json5@^2.2.3: +json5@^2.2.2, json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -8220,7 +9035,7 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -kleur@^4.1.5: +kleur@^4.0.3, kleur@^4.1.5: version "4.1.5" resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== @@ -8337,6 +9152,19 @@ load-yaml-file@^0.2.0: pify "^4.0.1" strip-bom "^3.0.0" +loader-utils@^3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.2.1.tgz#4fb104b599daafd82ef3e1a41fb9265f87e1f576" + integrity sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw== + +local-pkg@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-0.5.0.tgz#093d25a346bae59a99f80e75f6e9d36d7e8c925c" + integrity sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg== + dependencies: + mlly "^1.4.2" + pkg-types "^1.0.3" + locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -8351,6 +9179,16 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== + lodash.isequal@4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" @@ -8376,6 +9214,14 @@ lodash@^4.17.21: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + log-symbols@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-5.1.0.tgz#a20e3b9a5f53fac6aeb8e2bb22c07cf2c8f16d93" @@ -8428,6 +9274,11 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +lru-cache@^7.4.4, lru-cache@^7.5.1, lru-cache@^7.7.1: + version "7.18.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" + integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== + lucide-react@^0.331.0: version "0.331.0" resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.331.0.tgz#06a566303a4b2f4f84aadea6f5ba3312ed5e04ad" @@ -8467,6 +9318,11 @@ mark.js@^8.11.1: resolved "https://registry.yarnpkg.com/mark.js/-/mark.js-8.11.1.tgz#180f1f9ebef8b0e638e4166ad52db879beb2ffc5" integrity sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ== +markdown-extensions@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/markdown-extensions/-/markdown-extensions-1.1.1.tgz#fea03b539faeaee9b4ef02a3769b455b189f7fc3" + integrity sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q== + markdown-extensions@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/markdown-extensions/-/markdown-extensions-2.0.0.tgz#34bebc83e9938cae16e0e017e4a9814a8330d3c4" @@ -8477,6 +9333,15 @@ markdown-table@^3.0.0: resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-3.0.3.tgz#e6331d30e493127e031dd385488b5bd326e4a6bd" integrity sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw== +mdast-util-definitions@^5.0.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz#9910abb60ac5d7115d6819b57ae0bcef07a3f7a7" + integrity sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + unist-util-visit "^4.0.0" + mdast-util-directive@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mdast-util-directive/-/mdast-util-directive-3.0.0.tgz#3fb1764e705bbdf0afb0d3f889e4404c3e82561f" @@ -8501,6 +9366,24 @@ mdast-util-find-and-replace@^3.0.0: unist-util-is "^6.0.0" unist-util-visit-parents "^6.0.0" +mdast-util-from-markdown@^1.0.0, mdast-util-from-markdown@^1.1.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz#9421a5a247f10d31d2faed2a30df5ec89ceafcf0" + integrity sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + decode-named-character-reference "^1.0.0" + mdast-util-to-string "^3.1.0" + micromark "^3.0.0" + micromark-util-decode-numeric-character-reference "^1.0.0" + micromark-util-decode-string "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + unist-util-stringify-position "^3.0.0" + uvu "^0.5.0" + mdast-util-from-markdown@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz#52f14815ec291ed061f2922fd14d6689c810cb88" @@ -8519,6 +9402,15 @@ mdast-util-from-markdown@^2.0.0: micromark-util-types "^2.0.0" unist-util-stringify-position "^4.0.0" +mdast-util-frontmatter@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-frontmatter/-/mdast-util-frontmatter-1.0.1.tgz#79c46d7414eb9d3acabe801ee4a70a70b75e5af1" + integrity sha512-JjA2OjxRqAa8wEG8hloD0uTU0kdn8kbtOWpPP94NBkfAlbxn4S8gCGf/9DwFtEeGPXrDcNXdiDjVaRdUFqYokw== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-to-markdown "^1.3.0" + micromark-extension-frontmatter "^1.0.0" + mdast-util-frontmatter@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/mdast-util-frontmatter/-/mdast-util-frontmatter-2.0.1.tgz#f5f929eb1eb36c8a7737475c7eb438261f964ee8" @@ -8596,6 +9488,17 @@ mdast-util-gfm@^3.0.0: mdast-util-gfm-task-list-item "^2.0.0" mdast-util-to-markdown "^2.0.0" +mdast-util-mdx-expression@^1.0.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mdast-util-mdx-expression/-/mdast-util-mdx-expression-1.3.2.tgz#d027789e67524d541d6de543f36d51ae2586f220" + integrity sha512-xIPmR5ReJDu/DHH1OoIT1HkuybIfRGYRywC+gJtI7qHjCJp/M9jrmBEJW22O8lskDWm562BX2W8TiAwRTb0rKA== + dependencies: + "@types/estree-jsx" "^1.0.0" + "@types/hast" "^2.0.0" + "@types/mdast" "^3.0.0" + mdast-util-from-markdown "^1.0.0" + mdast-util-to-markdown "^1.0.0" + mdast-util-mdx-expression@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.0.tgz#4968b73724d320a379110d853e943a501bfd9d87" @@ -8608,6 +9511,24 @@ mdast-util-mdx-expression@^2.0.0: mdast-util-from-markdown "^2.0.0" mdast-util-to-markdown "^2.0.0" +mdast-util-mdx-jsx@^2.0.0: + version "2.1.4" + resolved "https://registry.yarnpkg.com/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-2.1.4.tgz#7c1f07f10751a78963cfabee38017cbc8b7786d1" + integrity sha512-DtMn9CmVhVzZx3f+optVDF8yFgQVt7FghCRNdlIaS3X5Bnym3hZwPbg/XW86vdpKjlc1PVj26SpnLGeJBXD3JA== + dependencies: + "@types/estree-jsx" "^1.0.0" + "@types/hast" "^2.0.0" + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + ccount "^2.0.0" + mdast-util-from-markdown "^1.1.0" + mdast-util-to-markdown "^1.3.0" + parse-entities "^4.0.0" + stringify-entities "^4.0.0" + unist-util-remove-position "^4.0.0" + unist-util-stringify-position "^3.0.0" + vfile-message "^3.0.0" + mdast-util-mdx-jsx@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.2.tgz#daae777c72f9c4a106592e3025aa50fb26068e1b" @@ -8627,6 +9548,17 @@ mdast-util-mdx-jsx@^3.0.0: unist-util-stringify-position "^4.0.0" vfile-message "^4.0.0" +mdast-util-mdx@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-mdx/-/mdast-util-mdx-2.0.1.tgz#49b6e70819b99bb615d7223c088d295e53bb810f" + integrity sha512-38w5y+r8nyKlGvNjSEqWrhG0w5PmnRA+wnBvm+ulYCct7nsGYhFVb0lljS9bQav4psDAS1eGkP2LMVcZBi/aqw== + dependencies: + mdast-util-from-markdown "^1.0.0" + mdast-util-mdx-expression "^1.0.0" + mdast-util-mdx-jsx "^2.0.0" + mdast-util-mdxjs-esm "^1.0.0" + mdast-util-to-markdown "^1.0.0" + mdast-util-mdx@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz#792f9cf0361b46bee1fdf1ef36beac424a099c41" @@ -8638,6 +9570,17 @@ mdast-util-mdx@^3.0.0: mdast-util-mdxjs-esm "^2.0.0" mdast-util-to-markdown "^2.0.0" +mdast-util-mdxjs-esm@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-1.3.1.tgz#645d02cd607a227b49721d146fd81796b2e2d15b" + integrity sha512-SXqglS0HrEvSdUEfoXFtcg7DRl7S2cwOXc7jkuusG472Mmjag34DUDeOJUZtl+BVnyeO1frIgVpHlNRWc2gk/w== + dependencies: + "@types/estree-jsx" "^1.0.0" + "@types/hast" "^2.0.0" + "@types/mdast" "^3.0.0" + mdast-util-from-markdown "^1.0.0" + mdast-util-to-markdown "^1.0.0" + mdast-util-mdxjs-esm@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz#019cfbe757ad62dd557db35a695e7314bcc9fa97" @@ -8650,6 +9593,14 @@ mdast-util-mdxjs-esm@^2.0.0: mdast-util-from-markdown "^2.0.0" mdast-util-to-markdown "^2.0.0" +mdast-util-phrasing@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-phrasing/-/mdast-util-phrasing-3.0.1.tgz#c7c21d0d435d7fb90956038f02e8702781f95463" + integrity sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg== + dependencies: + "@types/mdast" "^3.0.0" + unist-util-is "^5.0.0" + mdast-util-phrasing@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz#7cc0a8dec30eaf04b7b1a9661a92adb3382aa6e3" @@ -8658,6 +9609,20 @@ mdast-util-phrasing@^4.0.0: "@types/mdast" "^4.0.0" unist-util-is "^6.0.0" +mdast-util-to-hast@^12.1.0: + version "12.3.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-12.3.0.tgz#045d2825fb04374e59970f5b3f279b5700f6fb49" + integrity sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw== + dependencies: + "@types/hast" "^2.0.0" + "@types/mdast" "^3.0.0" + mdast-util-definitions "^5.0.0" + micromark-util-sanitize-uri "^1.1.0" + trim-lines "^3.0.0" + unist-util-generated "^2.0.0" + unist-util-position "^4.0.0" + unist-util-visit "^4.0.0" + mdast-util-to-hast@^13.0.0, mdast-util-to-hast@^13.0.2: version "13.1.0" resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-13.1.0.tgz#1ae54d903150a10fe04d59f03b2b95fd210b2124" @@ -8673,6 +9638,20 @@ mdast-util-to-hast@^13.0.0, mdast-util-to-hast@^13.0.2: unist-util-visit "^5.0.0" vfile "^6.0.0" +mdast-util-to-markdown@^1.0.0, mdast-util-to-markdown@^1.3.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-1.5.0.tgz#c13343cb3fc98621911d33b5cd42e7d0731171c6" + integrity sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + longest-streak "^3.0.0" + mdast-util-phrasing "^3.0.0" + mdast-util-to-string "^3.0.0" + micromark-util-decode-string "^1.0.0" + unist-util-visit "^4.0.0" + zwitch "^2.0.0" + mdast-util-to-markdown@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz#9813f1d6e0cdaac7c244ec8c6dabfdb2102ea2b4" @@ -8687,6 +9666,13 @@ mdast-util-to-markdown@^2.0.0: unist-util-visit "^5.0.0" zwitch "^2.0.0" +mdast-util-to-string@^3.0.0, mdast-util-to-string@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz#66f7bb6324756741c5f47a53557f0cbf16b6f789" + integrity sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-to-string@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz#7a5121475556a04e7eddeb67b264aae79d312814" @@ -8755,6 +9741,28 @@ micro-ftch@^0.3.1: resolved "https://registry.yarnpkg.com/micro-ftch/-/micro-ftch-0.3.1.tgz#6cb83388de4c1f279a034fb0cf96dfc050853c5f" integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg== +micromark-core-commonmark@^1.0.0, micromark-core-commonmark@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz#1386628df59946b2d39fb2edfd10f3e8e0a75bb8" + integrity sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw== + dependencies: + decode-named-character-reference "^1.0.0" + micromark-factory-destination "^1.0.0" + micromark-factory-label "^1.0.0" + micromark-factory-space "^1.0.0" + micromark-factory-title "^1.0.0" + micromark-factory-whitespace "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-chunked "^1.0.0" + micromark-util-classify-character "^1.0.0" + micromark-util-html-tag-name "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-resolve-all "^1.0.0" + micromark-util-subtokenize "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.1" + uvu "^0.5.0" + micromark-core-commonmark@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-2.0.0.tgz#50740201f0ee78c12a675bf3e68ffebc0bf931a3" @@ -8790,6 +9798,16 @@ micromark-extension-directive@^3.0.0: micromark-util-types "^2.0.0" parse-entities "^4.0.0" +micromark-extension-frontmatter@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/micromark-extension-frontmatter/-/micromark-extension-frontmatter-1.1.1.tgz#2946643938e491374145d0c9aacc3249e38a865f" + integrity sha512-m2UH9a7n3W8VAH9JO9y01APpPKmNNNs71P0RbknEmYSaZU5Ghogv38BYO94AI5Xw6OYfxZRdHZZ2nYjs/Z+SZQ== + dependencies: + fault "^2.0.0" + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + micromark-extension-frontmatter@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/micromark-extension-frontmatter/-/micromark-extension-frontmatter-2.0.0.tgz#651c52ffa5d7a8eeed687c513cd869885882d67a" @@ -8879,6 +9897,20 @@ micromark-extension-gfm@^3.0.0: micromark-util-combine-extensions "^2.0.0" micromark-util-types "^2.0.0" +micromark-extension-mdx-expression@^1.0.0: + version "1.0.8" + resolved "https://registry.yarnpkg.com/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-1.0.8.tgz#5bc1f5fd90388e8293b3ef4f7c6f06c24aff6314" + integrity sha512-zZpeQtc5wfWKdzDsHRBY003H2Smg+PUi2REhqgIhdzAa5xonhP03FcXxqFSerFiNUr5AWmHpaNPQTBVOS4lrXw== + dependencies: + "@types/estree" "^1.0.0" + micromark-factory-mdx-expression "^1.0.0" + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-events-to-acorn "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + micromark-extension-mdx-expression@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.0.tgz#1407b9ce69916cf5e03a196ad9586889df25302a" @@ -8893,6 +9925,22 @@ micromark-extension-mdx-expression@^3.0.0: micromark-util-symbol "^2.0.0" micromark-util-types "^2.0.0" +micromark-extension-mdx-jsx@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-1.0.5.tgz#e72d24b7754a30d20fb797ece11e2c4e2cae9e82" + integrity sha512-gPH+9ZdmDflbu19Xkb8+gheqEDqkSpdCEubQyxuz/Hn8DOXiXvrXeikOoBA71+e8Pfi0/UYmU3wW3H58kr7akA== + dependencies: + "@types/acorn" "^4.0.0" + "@types/estree" "^1.0.0" + estree-util-is-identifier-name "^2.0.0" + micromark-factory-mdx-expression "^1.0.0" + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + vfile-message "^3.0.0" + micromark-extension-mdx-jsx@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.0.tgz#4aba0797c25efb2366a3fd2d367c6b1c1159f4f5" @@ -8909,6 +9957,13 @@ micromark-extension-mdx-jsx@^3.0.0: micromark-util-types "^2.0.0" vfile-message "^4.0.0" +micromark-extension-mdx-md@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/micromark-extension-mdx-md/-/micromark-extension-mdx-md-1.0.1.tgz#595d4b2f692b134080dca92c12272ab5b74c6d1a" + integrity sha512-7MSuj2S7xjOQXAjjkbjBsHkMtb+mDGVW6uI2dBL9snOBCbZmoNgDAeZ0nSn9j3T42UE/g2xVNMn18PJxZvkBEA== + dependencies: + micromark-util-types "^1.0.0" + micromark-extension-mdx-md@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz#1d252881ea35d74698423ab44917e1f5b197b92d" @@ -8916,6 +9971,21 @@ micromark-extension-mdx-md@^2.0.0: dependencies: micromark-util-types "^2.0.0" +micromark-extension-mdxjs-esm@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-1.0.5.tgz#e4f8be9c14c324a80833d8d3a227419e2b25dec1" + integrity sha512-xNRBw4aoURcyz/S69B19WnZAkWJMxHMT5hE36GtDAyhoyn/8TuAeqjFJQlwk+MKQsUD7b3l7kFX+vlfVWgcX1w== + dependencies: + "@types/estree" "^1.0.0" + micromark-core-commonmark "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-events-to-acorn "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + unist-util-position-from-estree "^1.1.0" + uvu "^0.5.0" + vfile-message "^3.0.0" + micromark-extension-mdxjs-esm@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz#de21b2b045fd2059bd00d36746081de38390d54a" @@ -8931,6 +10001,20 @@ micromark-extension-mdxjs-esm@^3.0.0: unist-util-position-from-estree "^2.0.0" vfile-message "^4.0.0" +micromark-extension-mdxjs@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/micromark-extension-mdxjs/-/micromark-extension-mdxjs-1.0.1.tgz#f78d4671678d16395efeda85170c520ee795ded8" + integrity sha512-7YA7hF6i5eKOfFUzZ+0z6avRG52GpWR8DL+kN47y3f2KhxbBZMhmxe7auOeaTBrW2DenbbZTf1ea9tA2hDpC2Q== + dependencies: + acorn "^8.0.0" + acorn-jsx "^5.0.0" + micromark-extension-mdx-expression "^1.0.0" + micromark-extension-mdx-jsx "^1.0.0" + micromark-extension-mdx-md "^1.0.0" + micromark-extension-mdxjs-esm "^1.0.0" + micromark-util-combine-extensions "^1.0.0" + micromark-util-types "^1.0.0" + micromark-extension-mdxjs@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz#b5a2e0ed449288f3f6f6c544358159557549de18" @@ -8945,6 +10029,15 @@ micromark-extension-mdxjs@^3.0.0: micromark-util-combine-extensions "^2.0.0" micromark-util-types "^2.0.0" +micromark-factory-destination@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz#eb815957d83e6d44479b3df640f010edad667b9f" + integrity sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + micromark-factory-destination@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz#857c94debd2c873cba34e0445ab26b74f6a6ec07" @@ -8954,6 +10047,16 @@ micromark-factory-destination@^2.0.0: micromark-util-symbol "^2.0.0" micromark-util-types "^2.0.0" +micromark-factory-label@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz#cc95d5478269085cfa2a7282b3de26eb2e2dec68" + integrity sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + micromark-factory-label@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz#17c5c2e66ce39ad6f4fc4cbf40d972f9096f726a" @@ -8964,6 +10067,20 @@ micromark-factory-label@^2.0.0: micromark-util-symbol "^2.0.0" micromark-util-types "^2.0.0" +micromark-factory-mdx-expression@^1.0.0: + version "1.0.9" + resolved "https://registry.yarnpkg.com/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-1.0.9.tgz#57ba4571b69a867a1530f34741011c71c73a4976" + integrity sha512-jGIWzSmNfdnkJq05c7b0+Wv0Kfz3NJ3N4cBjnbO4zjXIlxJr+f8lk+5ZmwFvqdAbUy2q6B5rCY//g0QAAaXDWA== + dependencies: + "@types/estree" "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-events-to-acorn "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + unist-util-position-from-estree "^1.0.0" + uvu "^0.5.0" + vfile-message "^3.0.0" + micromark-factory-mdx-expression@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.1.tgz#f2a9724ce174f1751173beb2c1f88062d3373b1b" @@ -8978,6 +10095,14 @@ micromark-factory-mdx-expression@^2.0.0: unist-util-position-from-estree "^2.0.0" vfile-message "^4.0.0" +micromark-factory-space@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz#c8f40b0640a0150751d3345ed885a080b0d15faf" + integrity sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-types "^1.0.0" + micromark-factory-space@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz#5e7afd5929c23b96566d0e1ae018ae4fcf81d030" @@ -8986,6 +10111,16 @@ micromark-factory-space@^2.0.0: micromark-util-character "^2.0.0" micromark-util-types "^2.0.0" +micromark-factory-title@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz#dd0fe951d7a0ac71bdc5ee13e5d1465ad7f50ea1" + integrity sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ== + dependencies: + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + micromark-factory-title@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz#726140fc77892af524705d689e1cf06c8a83ea95" @@ -8996,6 +10131,16 @@ micromark-factory-title@^2.0.0: micromark-util-symbol "^2.0.0" micromark-util-types "^2.0.0" +micromark-factory-whitespace@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz#798fb7489f4c8abafa7ca77eed6b5745853c9705" + integrity sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ== + dependencies: + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + micromark-factory-whitespace@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz#9e92eb0f5468083381f923d9653632b3cfb5f763" @@ -9006,6 +10151,14 @@ micromark-factory-whitespace@^2.0.0: micromark-util-symbol "^2.0.0" micromark-util-types "^2.0.0" +micromark-util-character@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-1.2.0.tgz#4fedaa3646db249bc58caeb000eb3549a8ca5dcc" + integrity sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg== + dependencies: + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + micromark-util-character@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-2.1.0.tgz#31320ace16b4644316f6bf057531689c71e2aee1" @@ -9014,6 +10167,13 @@ micromark-util-character@^2.0.0: micromark-util-symbol "^2.0.0" micromark-util-types "^2.0.0" +micromark-util-chunked@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz#37a24d33333c8c69a74ba12a14651fd9ea8a368b" + integrity sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ== + dependencies: + micromark-util-symbol "^1.0.0" + micromark-util-chunked@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz#e51f4db85fb203a79dbfef23fd41b2f03dc2ef89" @@ -9021,6 +10181,15 @@ micromark-util-chunked@^2.0.0: dependencies: micromark-util-symbol "^2.0.0" +micromark-util-classify-character@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz#6a7f8c8838e8a120c8e3c4f2ae97a2bff9190e9d" + integrity sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + micromark-util-classify-character@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz#8c7537c20d0750b12df31f86e976d1d951165f34" @@ -9030,6 +10199,14 @@ micromark-util-classify-character@^2.0.0: micromark-util-symbol "^2.0.0" micromark-util-types "^2.0.0" +micromark-util-combine-extensions@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz#192e2b3d6567660a85f735e54d8ea6e3952dbe84" + integrity sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA== + dependencies: + micromark-util-chunked "^1.0.0" + micromark-util-types "^1.0.0" + micromark-util-combine-extensions@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz#75d6ab65c58b7403616db8d6b31315013bfb7ee5" @@ -9038,6 +10215,13 @@ micromark-util-combine-extensions@^2.0.0: micromark-util-chunked "^2.0.0" micromark-util-types "^2.0.0" +micromark-util-decode-numeric-character-reference@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz#b1e6e17009b1f20bc652a521309c5f22c85eb1c6" + integrity sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw== + dependencies: + micromark-util-symbol "^1.0.0" + micromark-util-decode-numeric-character-reference@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz#2698bbb38f2a9ba6310e359f99fcb2b35a0d2bd5" @@ -9045,6 +10229,16 @@ micromark-util-decode-numeric-character-reference@^2.0.0: dependencies: micromark-util-symbol "^2.0.0" +micromark-util-decode-string@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz#dc12b078cba7a3ff690d0203f95b5d5537f2809c" + integrity sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ== + dependencies: + decode-named-character-reference "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-decode-numeric-character-reference "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-decode-string@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz#7dfa3a63c45aecaa17824e656bcdb01f9737154a" @@ -9055,11 +10249,30 @@ micromark-util-decode-string@^2.0.0: micromark-util-decode-numeric-character-reference "^2.0.0" micromark-util-symbol "^2.0.0" +micromark-util-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz#92e4f565fd4ccb19e0dcae1afab9a173bbeb19a5" + integrity sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw== + micromark-util-encode@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz#0921ac7953dc3f1fd281e3d1932decfdb9382ab1" integrity sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA== +micromark-util-events-to-acorn@^1.0.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-1.2.3.tgz#a4ab157f57a380e646670e49ddee97a72b58b557" + integrity sha512-ij4X7Wuc4fED6UoLWkmo0xJQhsktfNh1J0m8g4PbIMPlx+ek/4YdW5mvbye8z/aZvAPUoxgXHrwVlXAPKMRp1w== + dependencies: + "@types/acorn" "^4.0.0" + "@types/estree" "^1.0.0" + "@types/unist" "^2.0.0" + estree-util-visit "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + vfile-message "^3.0.0" + micromark-util-events-to-acorn@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.2.tgz#4275834f5453c088bd29cd72dfbf80e3327cec07" @@ -9074,11 +10287,23 @@ micromark-util-events-to-acorn@^2.0.0: micromark-util-types "^2.0.0" vfile-message "^4.0.0" +micromark-util-html-tag-name@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz#48fd7a25826f29d2f71479d3b4e83e94829b3588" + integrity sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q== + micromark-util-html-tag-name@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz#ae34b01cbe063363847670284c6255bb12138ec4" integrity sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw== +micromark-util-normalize-identifier@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz#7a73f824eb9f10d442b4d7f120fecb9b38ebf8b7" + integrity sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q== + dependencies: + micromark-util-symbol "^1.0.0" + micromark-util-normalize-identifier@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz#91f9a4e65fe66cc80c53b35b0254ad67aa431d8b" @@ -9086,6 +10311,13 @@ micromark-util-normalize-identifier@^2.0.0: dependencies: micromark-util-symbol "^2.0.0" +micromark-util-resolve-all@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz#4652a591ee8c8fa06714c9b54cd6c8e693671188" + integrity sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA== + dependencies: + micromark-util-types "^1.0.0" + micromark-util-resolve-all@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz#189656e7e1a53d0c86a38a652b284a252389f364" @@ -9093,6 +10325,15 @@ micromark-util-resolve-all@^2.0.0: dependencies: micromark-util-types "^2.0.0" +micromark-util-sanitize-uri@^1.0.0, micromark-util-sanitize-uri@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz#613f738e4400c6eedbc53590c67b197e30d7f90d" + integrity sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-encode "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-sanitize-uri@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz#ec8fbf0258e9e6d8f13d9e4770f9be64342673de" @@ -9102,6 +10343,16 @@ micromark-util-sanitize-uri@^2.0.0: micromark-util-encode "^2.0.0" micromark-util-symbol "^2.0.0" +micromark-util-subtokenize@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz#941c74f93a93eaf687b9054aeb94642b0e92edb1" + integrity sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A== + dependencies: + micromark-util-chunked "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + micromark-util-subtokenize@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.0.tgz#9f412442d77e0c5789ffdf42377fa8a2bcbdf581" @@ -9112,16 +10363,49 @@ micromark-util-subtokenize@^2.0.0: micromark-util-symbol "^2.0.0" micromark-util-types "^2.0.0" +micromark-util-symbol@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz#813cd17837bdb912d069a12ebe3a44b6f7063142" + integrity sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag== + micromark-util-symbol@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz#12225c8f95edf8b17254e47080ce0862d5db8044" integrity sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw== +micromark-util-types@^1.0.0, micromark-util-types@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-1.1.0.tgz#e6676a8cae0bb86a2171c498167971886cb7e283" + integrity sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg== + micromark-util-types@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-2.0.0.tgz#63b4b7ffeb35d3ecf50d1ca20e68fc7caa36d95e" integrity sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w== +micromark@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/micromark/-/micromark-3.2.0.tgz#1af9fef3f995ea1ea4ac9c7e2f19c48fd5c006e9" + integrity sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA== + dependencies: + "@types/debug" "^4.0.0" + debug "^4.0.0" + decode-named-character-reference "^1.0.0" + micromark-core-commonmark "^1.0.1" + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-chunked "^1.0.0" + micromark-util-combine-extensions "^1.0.0" + micromark-util-decode-numeric-character-reference "^1.0.0" + micromark-util-encode "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-resolve-all "^1.0.0" + micromark-util-sanitize-uri "^1.0.0" + micromark-util-subtokenize "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.1" + uvu "^0.5.0" + micromark@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/micromark/-/micromark-4.0.0.tgz#84746a249ebd904d9658cfabc1e8e5f32cbc6249" @@ -9195,6 +10479,24 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== +miniflare@^3.20231218.2: + version "3.20240320.0" + resolved "https://registry.yarnpkg.com/miniflare/-/miniflare-3.20240320.0.tgz#45f601e61529c84c7b37248c8ca133eaafad76ec" + integrity sha512-4M2QRxs+J5sUsybBzKT++tlbrjjjGZdtWxKmj2sqLsT26dGaKDz7DxjAeF5XIhKa5cADcffygjxx4EvfWocMmw== + dependencies: + "@cspotcode/source-map-support" "0.8.1" + acorn "^8.8.0" + acorn-walk "^8.2.0" + capnp-ts "^0.7.0" + exit-hook "^2.2.1" + glob-to-regexp "^0.4.1" + stoppable "^1.1.0" + undici "^5.28.2" + workerd "1.20240320.1" + ws "^8.11.0" + youch "^3.2.2" + zod "^3.20.6" + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -9205,7 +10507,7 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== -minimatch@9.0.3, minimatch@^9.0.1, minimatch@^9.0.3: +minimatch@9.0.3, minimatch@^9.0.0, minimatch@^9.0.1, minimatch@^9.0.3: version "9.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== @@ -9233,7 +10535,40 @@ minimist@^1.2.0, minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0": +minipass-collect@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" + integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== + dependencies: + minipass "^3.0.0" + +minipass-flush@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" + integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== + dependencies: + minipass "^3.0.0" + +minipass-pipeline@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" + integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== + dependencies: + minipass "^3.0.0" + +minipass@^3.0.0: + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== + dependencies: + yallist "^4.0.0" + +minipass@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.3: version "7.0.4" resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== @@ -9243,6 +10578,14 @@ minisearch@^6.3.0: resolved "https://registry.yarnpkg.com/minisearch/-/minisearch-6.3.0.tgz#985a2f1ca3c73c2d65af94f0616bfe57164b0b6b" integrity sha512-ihFnidEeU8iXzcVHy74dhkxh/dn8Dc08ERl0xwoMMGqp4+LvRSCgicb+zGqWthVokQKvCSxITlh3P08OzdTYCQ== +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + mipd@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/mipd/-/mipd-0.0.5.tgz#367ee796531c23f0631f129038700b1406663aec" @@ -9255,6 +10598,16 @@ mixme@^0.5.1: resolved "https://registry.yarnpkg.com/mixme/-/mixme-0.5.10.tgz#d653b2984b75d9018828f1ea333e51717ead5f51" integrity sha512-5H76ANWinB1H3twpJ6JY8uvAtpmFvHNArpilJAjXRKXSDDLPIMoZArw5SH0q9z+lLs8IrMw7Q2VWpWimFKFT1Q== +mkdirp-classic@^0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + mlly@^1.2.0, mlly@^1.4.2, mlly@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.6.1.tgz#0983067dc3366d6314fc5e12712884e6978d028f" @@ -9270,6 +10623,17 @@ modern-ahocorasick@^1.0.0: resolved "https://registry.yarnpkg.com/modern-ahocorasick/-/modern-ahocorasick-1.0.1.tgz#dec373444f51b5458ac05216a8ec376e126dd283" integrity sha512-yoe+JbhTClckZ67b2itRtistFKf8yPYelHLc7e5xAwtNAXxM6wJTUx2C7QeVSJFDzKT7bCIFyBVybPMKvmB9AA== +morgan@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" + integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ== + dependencies: + basic-auth "~2.0.1" + debug "2.6.9" + depd "~2.0.0" + on-finished "~2.3.0" + on-headers "~1.0.2" + motion@10.16.2: version "10.16.2" resolved "https://registry.yarnpkg.com/motion/-/motion-10.16.2.tgz#7dc173c6ad62210a7e9916caeeaf22c51e598d21" @@ -9282,7 +10646,7 @@ motion@10.16.2: "@motionone/utils" "^10.15.1" "@motionone/vue" "^10.16.2" -mri@^1.2.0: +mri@^1.1.0, mri@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== @@ -9292,6 +10656,11 @@ mrmime@^1.0.0: resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.1.tgz#5f90c825fad4bdd41dc914eff5d1a8cfdaf24f27" integrity sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw== +mrmime@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-2.0.0.tgz#151082a6e06e59a9a39b46b3e14d5cfe92b3abb4" + integrity sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -9312,6 +10681,11 @@ multiformats@^9.4.2: resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.9.0.tgz#c68354e7d21037a8f1f8833c8ccd68618e8f1d37" integrity sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg== +mustache@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.2.0.tgz#e5892324d60a12ec9c2a73359edca52972bf6f64" + integrity sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ== + mz@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" @@ -9346,29 +10720,6 @@ neverthrow@^6.0.0: resolved "https://registry.yarnpkg.com/neverthrow/-/neverthrow-6.1.0.tgz#51a6e9ce2e06600045b3c1b37aecc536d267bf95" integrity sha512-xNbNjp/6M5vUV+mststgneJN9eJeJCDSYSBTaf3vxgvcKooP+8L0ATFpM8DGfmH7UWKJeoa24Qi33tBP9Ya3zA== -next@14.1.0: - version "14.1.0" - resolved "https://registry.yarnpkg.com/next/-/next-14.1.0.tgz#b31c0261ff9caa6b4a17c5af019ed77387174b69" - integrity sha512-wlzrsbfeSU48YQBjZhDzOwhWhGsy+uQycR8bHAOt1LY1bn3zZEcDyHQOEoN3aWzQ8LHCAJ1nqrWCc9XF2+O45Q== - dependencies: - "@next/env" "14.1.0" - "@swc/helpers" "0.5.2" - busboy "1.6.0" - caniuse-lite "^1.0.30001579" - graceful-fs "^4.2.11" - postcss "8.4.31" - styled-jsx "5.1.1" - optionalDependencies: - "@next/swc-darwin-arm64" "14.1.0" - "@next/swc-darwin-x64" "14.1.0" - "@next/swc-linux-arm64-gnu" "14.1.0" - "@next/swc-linux-arm64-musl" "14.1.0" - "@next/swc-linux-x64-gnu" "14.1.0" - "@next/swc-linux-x64-musl" "14.1.0" - "@next/swc-win32-arm64-msvc" "14.1.0" - "@next/swc-win32-ia32-msvc" "14.1.0" - "@next/swc-win32-x64-msvc" "14.1.0" - next@^14.0.4, next@^14.1.0, next@^14.1.2, next@^14.1.3: version "14.1.4" resolved "https://registry.yarnpkg.com/next/-/next-14.1.4.tgz#203310f7310578563fd5c961f0db4729ce7a502d" @@ -9457,6 +10808,16 @@ normalize-package-data@^2.5.0: semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" +normalize-package-data@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-5.0.0.tgz#abcb8d7e724c40d88462b84982f7cbf6859b4588" + integrity sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q== + dependencies: + hosted-git-info "^6.0.0" + is-core-module "^2.8.1" + semver "^7.3.5" + validate-npm-package-license "^3.0.4" + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -9472,6 +10833,38 @@ not@^0.1.0: resolved "https://registry.yarnpkg.com/not/-/not-0.1.0.tgz#c9691c1746c55dcfbe54cbd8bd4ff041bc2b519d" integrity sha512-5PDmaAsVfnWUgTUbJ3ERwn7u79Z0dYxN9ErxCpVJJqe2RK0PJ3z+iFUxuqjwtlDDegXvtWoxD/3Fzxox7tFGWA== +npm-install-checks@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-6.3.0.tgz#046552d8920e801fa9f919cad569545d60e826fe" + integrity sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw== + dependencies: + semver "^7.1.1" + +npm-normalize-package-bin@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz#25447e32a9a7de1f51362c61a559233b89947832" + integrity sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ== + +npm-package-arg@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-10.1.0.tgz#827d1260a683806685d17193073cc152d3c7e9b1" + integrity sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA== + dependencies: + hosted-git-info "^6.0.0" + proc-log "^3.0.0" + semver "^7.3.5" + validate-npm-package-name "^5.0.0" + +npm-pick-manifest@^8.0.0: + version "8.0.2" + resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-8.0.2.tgz#2159778d9c7360420c925c1a2287b5a884c713aa" + integrity sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg== + dependencies: + npm-install-checks "^6.0.0" + npm-normalize-package-bin "^3.0.0" + npm-package-arg "^10.0.0" + semver "^7.3.5" + npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" @@ -9603,6 +10996,13 @@ on-finished@2.4.1: dependencies: ee-first "1.1.1" +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== + dependencies: + ee-first "1.1.1" + on-headers@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" @@ -9660,6 +11060,21 @@ optionator@^0.9.3: prelude-ls "^1.2.1" type-check "^0.4.0" +ora@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" + integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== + dependencies: + bl "^4.1.0" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-spinners "^2.5.0" + is-interactive "^1.0.0" + is-unicode-supported "^0.1.0" + log-symbols "^4.1.0" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + ora@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/ora/-/ora-7.0.1.tgz#cdd530ecd865fe39e451a0e7697865669cb11930" @@ -9730,12 +11145,19 @@ p-map@^2.0.0: resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -pako@^0.2.5: +pako@^0.2.5, pako@~0.2.0: version "0.2.9" resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" integrity sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA== @@ -9779,6 +11201,11 @@ parse-json@^5.0.0, parse-json@^5.2.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" +parse-ms@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-2.1.0.tgz#348565a753d4391fa524029956b172cb7753097d" + integrity sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA== + parse5-htmlparser2-tree-adapter@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz#23c2cc233bcf09bb7beba8b8a69d46b08c62c2f1" @@ -9847,6 +11274,15 @@ pathe@^1.1.0, pathe@^1.1.1, pathe@^1.1.2: resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec" integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ== +peek-stream@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/peek-stream/-/peek-stream-1.1.3.tgz#3b35d84b7ccbbd262fff31dc10da56856ead6d67" + integrity sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA== + dependencies: + buffer-from "^1.0.0" + duplexify "^3.5.0" + through2 "^2.0.3" + periscopic@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/periscopic/-/periscopic-3.1.0.tgz#7e9037bf51c5855bd33b48928828db4afa79d97a" @@ -9866,6 +11302,11 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pidtree@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c" + integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g== + pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -9957,6 +11398,11 @@ possible-typed-array-names@^1.0.0: resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== +postcss-discard-duplicates@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz#9eb4fe8456706a4eebd6d3b7b777d07bad03e848" + integrity sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw== + postcss-import@^15.1.0: version "15.1.0" resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70" @@ -9981,6 +11427,48 @@ postcss-load-config@^4.0.1: lilconfig "^3.0.0" yaml "^2.3.4" +postcss-modules-extract-imports@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" + integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== + +postcss-modules-local-by-default@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.4.tgz#7cbed92abd312b94aaea85b68226d3dec39a14e6" + integrity sha512-L4QzMnOdVwRm1Qb8m4x8jsZzKAaPAgrUF1r/hjDR2Xj7R+8Zsf97jAlSQzWtKx5YNiNGN8QxmPFIc/sh+RQl+Q== + dependencies: + icss-utils "^5.0.0" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + +postcss-modules-scope@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.1.1.tgz#32cfab55e84887c079a19bbb215e721d683ef134" + integrity sha512-uZgqzdTleelWjzJY+Fhti6F3C9iF1JR/dODLs/JDefozYcKTBCdD8BIl6nNPbTbcLnGrk56hzwZC2DaGNvYjzA== + dependencies: + postcss-selector-parser "^6.0.4" + +postcss-modules-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" + integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== + dependencies: + icss-utils "^5.0.0" + +postcss-modules@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules/-/postcss-modules-6.0.0.tgz#cac283dbabbbdc2558c45391cbd0e2df9ec50118" + integrity sha512-7DGfnlyi/ju82BRzTIjWS5C4Tafmzl3R79YP/PASiocj+aa6yYphHhhKUOEoXQToId5rgyFgJ88+ccOUydjBXQ== + dependencies: + generic-names "^4.0.0" + icss-utils "^5.1.0" + lodash.camelcase "^4.3.0" + postcss-modules-extract-imports "^3.0.0" + postcss-modules-local-by-default "^4.0.0" + postcss-modules-scope "^3.0.0" + postcss-modules-values "^4.0.0" + string-hash "^1.1.1" + postcss-nested@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.0.1.tgz#f83dc9846ca16d2f4fa864f16e9d9f7d0961662c" @@ -9988,7 +11476,7 @@ postcss-nested@^6.0.1: dependencies: postcss-selector-parser "^6.0.11" -postcss-selector-parser@^6.0.11: +postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: version "6.0.16" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz#3b88b9f5c5abd989ef4e2fc9ec8eedd34b20fb04" integrity sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw== @@ -9996,7 +11484,7 @@ postcss-selector-parser@^6.0.11: cssesc "^3.0.0" util-deprecate "^1.0.2" -postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^4.2.0: +postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== @@ -10010,7 +11498,7 @@ postcss@8.4.31: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^8, postcss@^8.3.6, postcss@^8.4.23, postcss@^8.4.31, postcss@^8.4.36: +postcss@^8, postcss@^8.3.6, postcss@^8.4.19, postcss@^8.4.23, postcss@^8.4.31, postcss@^8.4.36: version "8.4.38" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e" integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== @@ -10066,6 +11554,23 @@ pretty-format@^29.0.0, pretty-format@^29.7.0: ansi-styles "^5.0.0" react-is "^18.0.0" +pretty-ms@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-7.0.1.tgz#7d903eaab281f7d8e03c66f867e239dc32fb73e8" + integrity sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q== + dependencies: + parse-ms "^2.1.0" + +printable-characters@^1.0.42: + version "1.0.42" + resolved "https://registry.yarnpkg.com/printable-characters/-/printable-characters-1.0.42.tgz#3f18e977a9bd8eb37fcc4ff5659d7be90868b3d8" + integrity sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ== + +proc-log@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-3.0.0.tgz#fb05ef83ccd64fd7b20bbe9c8c1070fc08338dd8" + integrity sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A== + process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" @@ -10081,6 +11586,19 @@ process-warning@^1.0.0: resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-1.0.0.tgz#980a0b25dc38cd6034181be4b7726d89066b4616" integrity sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q== +promise-inflight@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g== + +promise-retry@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22" + integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g== + dependencies: + err-code "^2.0.2" + retry "^0.12.0" + prompts@^2.0.1: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" @@ -10144,6 +11662,14 @@ pseudomap@^1.0.2: resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== +pump@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + pump@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" @@ -10152,6 +11678,15 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" +pumpify@^1.3.3: + version "1.5.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== + dependencies: + duplexify "^3.6.0" + inherits "^2.0.3" + pump "^2.0.0" + punycode@^2.1.0: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" @@ -10342,7 +11877,7 @@ react-remove-scroll@2.5.7: use-callback-ref "^1.3.0" use-sidecar "^1.1.2" -react-router-dom@^6.20.0: +react-router-dom@6.22.3, react-router-dom@^6.20.0: version "6.22.3" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.22.3.tgz#9781415667fd1361a475146c5826d9f16752a691" integrity sha512-7ZILI7HjcE+p31oQvwbokjk6OA/bnFxrhJ19n82Ex9Ph8fNAq+Hm/7KchpMGlTgWhUxRHMMCut+vEtNpWpowKw== @@ -10427,7 +11962,7 @@ readable-stream@2.3.3: string_decoder "~1.0.3" util-deprecate "~1.0.1" -readable-stream@^2.3.3, readable-stream@^2.3.7: +readable-stream@^2.0.0, readable-stream@^2.3.3, readable-stream@^2.3.7, readable-stream@~2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== @@ -10552,6 +12087,16 @@ remark-directive@^3.0.0: micromark-extension-directive "^3.0.0" unified "^11.0.0" +remark-frontmatter@4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/remark-frontmatter/-/remark-frontmatter-4.0.1.tgz#84560f7ccef114ef076d3d3735be6d69f8922309" + integrity sha512-38fJrB0KnmD3E33a5jZC/5+gGAC2WKNiPw1/fdXJvijBlhA7RCsvJklrYJakS0HedninvaCYW8lQGf9C918GfA== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-frontmatter "^1.0.0" + micromark-extension-frontmatter "^1.0.0" + unified "^10.0.0" + remark-frontmatter@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/remark-frontmatter/-/remark-frontmatter-5.0.0.tgz#b68d61552a421ec412c76f4f66c344627dc187a2" @@ -10574,6 +12119,16 @@ remark-gfm@^4.0.0: remark-stringify "^11.0.0" unified "^11.0.0" +remark-mdx-frontmatter@^1.0.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/remark-mdx-frontmatter/-/remark-mdx-frontmatter-1.1.1.tgz#54cfb3821fbb9cb6057673e0570ae2d645f6fe32" + integrity sha512-7teX9DW4tI2WZkXS4DBxneYSY7NHiXl4AKdWDO9LXVweULlCT8OPWsOjLEnMIXViN1j+QcY8mfbq3k0EK6x3uA== + dependencies: + estree-util-is-identifier-name "^1.0.0" + estree-util-value-to-estree "^1.0.0" + js-yaml "^4.0.0" + toml "^3.0.0" + remark-mdx-frontmatter@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/remark-mdx-frontmatter/-/remark-mdx-frontmatter-4.0.0.tgz#1d0287103ac73c5d493d2fad19dd805e69db55ca" @@ -10586,6 +12141,14 @@ remark-mdx-frontmatter@^4.0.0: unified "^11.0.0" yaml "^2.0.0" +remark-mdx@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-2.3.0.tgz#efe678025a8c2726681bde8bf111af4a93943db4" + integrity sha512-g53hMkpM0I98MU266IzDFMrTD980gNF3BJnkyFcmN+dD873mQeD5rdMO3Y2X+x8umQfbSE0PcoEDl7ledSA+2g== + dependencies: + mdast-util-mdx "^2.0.0" + micromark-extension-mdxjs "^1.0.0" + remark-mdx@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-3.0.1.tgz#8f73dd635c1874e44426e243f72c0977cf60e212" @@ -10594,6 +12157,15 @@ remark-mdx@^3.0.0: mdast-util-mdx "^3.0.0" micromark-extension-mdxjs "^3.0.0" +remark-parse@^10.0.0: + version "10.0.2" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-10.0.2.tgz#ca241fde8751c2158933f031a4e3efbaeb8bc262" + integrity sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-from-markdown "^1.0.0" + unified "^10.0.0" + remark-parse@^11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-11.0.0.tgz#aa60743fcb37ebf6b069204eb4da304e40db45a1" @@ -10604,6 +12176,16 @@ remark-parse@^11.0.0: micromark-util-types "^2.0.0" unified "^11.0.0" +remark-rehype@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-10.1.0.tgz#32dc99d2034c27ecaf2e0150d22a6dcccd9a6279" + integrity sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw== + dependencies: + "@types/hast" "^2.0.0" + "@types/mdast" "^3.0.0" + mdast-util-to-hast "^12.1.0" + unified "^10.0.0" + remark-rehype@^11.0.0: version "11.1.0" resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-11.1.0.tgz#d5f264f42bcbd4d300f030975609d01a1697ccdc" @@ -10661,7 +12243,7 @@ resolve-pkg-maps@^1.0.0: resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== -resolve.exports@^2.0.0: +resolve.exports@^2.0.0, resolve.exports@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== @@ -10692,6 +12274,14 @@ resolve@~1.19.0: is-core-module "^2.1.0" path-parse "^1.0.6" +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + restore-cursor@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-4.0.0.tgz#519560a4318975096def6e609d44100edaa4ccb9" @@ -10700,6 +12290,11 @@ restore-cursor@^4.0.0: onetime "^5.1.0" signal-exit "^3.0.2" +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -10770,6 +12365,13 @@ rxjs@^7.8.0, rxjs@^7.8.1: dependencies: tslib "^2.1.0" +sade@^1.7.3: + version "1.8.1" + resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701" + integrity sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A== + dependencies: + mri "^1.1.0" + safe-array-concat@^1.1.0, safe-array-concat@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" @@ -10851,7 +12453,7 @@ semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4: +semver@^7.0.0, semver@^7.1.1, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4: version "7.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== @@ -10892,7 +12494,7 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== -set-cookie-parser@^2.4.8: +set-cookie-parser@^2.4.8, set-cookie-parser@^2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz#131921e50f62ff1a66a461d7d62d7b21d5d15a51" integrity sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ== @@ -10988,6 +12590,15 @@ signal-exit@^4.0.1, signal-exit@^4.1.0: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== +sirv@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-2.0.4.tgz#5dd9a725c578e34e449f332703eb2a74e46a29b0" + integrity sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ== + dependencies: + "@polka/url" "^1.0.0-next.24" + mrmime "^2.0.0" + totalist "^3.0.0" + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -11160,6 +12771,13 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== +ssri@^10.0.0: + version "10.0.5" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.5.tgz#e49efcd6e36385196cb515d3a2ad6c3f0265ef8c" + integrity sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A== + dependencies: + minipass "^7.0.3" + stack-utils@^2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" @@ -11167,6 +12785,14 @@ stack-utils@^2.0.3: dependencies: escape-string-regexp "^2.0.0" +stacktracey@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/stacktracey/-/stacktracey-2.1.8.tgz#bf9916020738ce3700d1323b32bd2c91ea71199d" + integrity sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw== + dependencies: + as-table "^1.0.36" + get-source "^2.0.12" + statuses@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" @@ -11184,7 +12810,12 @@ stdin-discarder@^0.1.0: dependencies: bl "^5.0.0" -stream-shift@^1.0.2: +stoppable@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/stoppable/-/stoppable-1.1.0.tgz#32da568e83ea488b08e4d7ea2c3bcc9d75015d5b" + integrity sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw== + +stream-shift@^1.0.0, stream-shift@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.3.tgz#85b8fab4d71010fc3ba8772e8046cc49b8a3864b" integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ== @@ -11211,6 +12842,11 @@ strict-uri-encode@^2.0.0: resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ== +string-hash@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" + integrity sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A== + string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" @@ -11372,7 +13008,7 @@ strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -style-to-object@^0.4.0: +style-to-object@^0.4.0, style-to-object@^0.4.1: version "0.4.4" resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.4.4.tgz#266e3dfd56391a7eefb7770423612d043c3f33ec" integrity sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg== @@ -11529,6 +13165,39 @@ tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== +tar-fs@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" + integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" + +tar-stream@^2.1.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + +tar@^6.1.11: + version "6.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" + integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^5.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + term-size@^2.1.0: version "2.2.1" resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54" @@ -11569,6 +13238,14 @@ thread-stream@^0.15.1: dependencies: real-require "^0.1.0" +through2@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + tiny-inflate@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz#122715494913a1805166aaf7c93467933eea26c4" @@ -11608,6 +13285,11 @@ toml@^3.0.0: resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee" integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w== +totalist@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/totalist/-/totalist-3.0.1.tgz#ba3a3d600c915b1a97872348f79c127475f6acf8" + integrity sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ== + tr46@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" @@ -11650,6 +13332,11 @@ ts-interface-checker@^0.1.9: resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== +tsconfck@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/tsconfck/-/tsconfck-3.0.3.tgz#d9bda0e87d05b1c360e996c9050473c7e6f8084f" + integrity sha512-4t0noZX9t6GcPTfBAbIbbIU4pfpCwh0ueq3S4O/5qXI1VwK1outmxhe9dOiEWqMz3MW2LKgDTpqWV+37IWuVbA== + tsconfig-paths@^3.15.0: version "3.15.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" @@ -11660,12 +13347,21 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" +tsconfig-paths@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" + integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== + dependencies: + json5 "^2.2.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + tslib@1.14.1, tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.6.2: +tslib@^2.0.0, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== @@ -11854,7 +13550,7 @@ typed-array-length@^1.0.5: is-typed-array "^1.1.13" possible-typed-array-names "^1.0.0" -typescript@^5.3.3: +typescript@^5.1.6, typescript@^5.3.3: version "5.4.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.3.tgz#5c6fedd4c87bee01cd7a528a30145521f8e0feff" integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg== @@ -11896,7 +13592,7 @@ undici-types@~5.26.4: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== -undici@^5.8.1: +undici@^5.28.2, undici@^5.8.1: version "5.28.3" resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.3.tgz#a731e0eff2c3fcfd41c1169a869062be222d1e5b" integrity sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA== @@ -11927,7 +13623,7 @@ unicode-trie@^2.0.0: pako "^0.2.5" tiny-inflate "^1.0.0" -unified@^10.1.2: +unified@^10.0.0, unified@^10.1.2: version "10.1.2" resolved "https://registry.yarnpkg.com/unified/-/unified-10.1.2.tgz#b1d64e55dafe1f0b98bb6c719881103ecf6c86df" integrity sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q== @@ -11953,6 +13649,32 @@ unified@^11.0.0, unified@^11.0.4: trough "^2.0.0" vfile "^6.0.0" +unique-filename@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-3.0.0.tgz#48ba7a5a16849f5080d26c760c86cf5cf05770ea" + integrity sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g== + dependencies: + unique-slug "^4.0.0" + +unique-slug@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-4.0.0.tgz#6bae6bb16be91351badd24cdce741f892a6532e3" + integrity sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ== + dependencies: + imurmurhash "^0.1.4" + +unist-util-generated@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-2.0.1.tgz#e37c50af35d3ed185ac6ceacb6ca0afb28a85cae" + integrity sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A== + +unist-util-is@^5.0.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-5.2.1.tgz#b74960e145c18dcb6226bc57933597f5486deae9" + integrity sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-6.0.0.tgz#b775956486aff107a9ded971d996c173374be424" @@ -11960,6 +13682,13 @@ unist-util-is@^6.0.0: dependencies: "@types/unist" "^3.0.0" +unist-util-position-from-estree@^1.0.0, unist-util-position-from-estree@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/unist-util-position-from-estree/-/unist-util-position-from-estree-1.1.2.tgz#8ac2480027229de76512079e377afbcabcfcce22" + integrity sha512-poZa0eXpS+/XpoQwGwl79UUdea4ol2ZuCYguVaJS4qzIOMDzbqz8a3erUCOmubSZkaOuGamb3tX790iwOIROww== + dependencies: + "@types/unist" "^2.0.0" + unist-util-position-from-estree@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz#d94da4df596529d1faa3de506202f0c9a23f2200" @@ -11967,6 +13696,13 @@ unist-util-position-from-estree@^2.0.0: dependencies: "@types/unist" "^3.0.0" +unist-util-position@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-4.0.4.tgz#93f6d8c7d6b373d9b825844645877c127455f037" + integrity sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg== + dependencies: + "@types/unist" "^2.0.0" + unist-util-position@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-5.0.0.tgz#678f20ab5ca1207a97d7ea8a388373c9cf896be4" @@ -11974,6 +13710,14 @@ unist-util-position@^5.0.0: dependencies: "@types/unist" "^3.0.0" +unist-util-remove-position@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-4.0.2.tgz#a89be6ea72e23b1a402350832b02a91f6a9afe51" + integrity sha512-TkBb0HABNmxzAcfLf4qsIbFbaPDvMO6wa3b3j4VcEzFVaw1LBKwnW4/sRJ/atSLSzoIg41JWEdnE7N6DIhGDGQ== + dependencies: + "@types/unist" "^2.0.0" + unist-util-visit "^4.0.0" + unist-util-remove-position@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz#fea68a25658409c9460408bc6b4991b965b52163" @@ -11996,6 +13740,14 @@ unist-util-stringify-position@^4.0.0: dependencies: "@types/unist" "^3.0.0" +unist-util-visit-parents@^5.1.1: + version "5.1.3" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz#b4520811b0ca34285633785045df7a8d6776cfeb" + integrity sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^5.0.0" + unist-util-visit-parents@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz#4d5f85755c3b8f0dc69e21eca5d6d82d22162815" @@ -12004,6 +13756,15 @@ unist-util-visit-parents@^6.0.0: "@types/unist" "^3.0.0" unist-util-is "^6.0.0" +unist-util-visit@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-4.1.2.tgz#125a42d1eb876283715a3cb5cceaa531828c72e2" + integrity sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^5.0.0" + unist-util-visit-parents "^5.1.1" + unist-util-visit@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-5.0.0.tgz#a7de1f31f72ffd3519ea71814cccf5fd6a9217d6" @@ -12131,6 +13892,16 @@ uuid@^9.0.1: resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== +uvu@^0.5.0: + version "0.5.6" + resolved "https://registry.yarnpkg.com/uvu/-/uvu-0.5.6.tgz#2754ca20bcb0bb59b64e9985e84d2e81058502df" + integrity sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA== + dependencies: + dequal "^2.0.0" + diff "^5.0.0" + kleur "^4.0.3" + sade "^1.7.3" + v8-to-istanbul@^9.0.1: version "9.2.0" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" @@ -12140,7 +13911,7 @@ v8-to-istanbul@^9.0.1: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^2.0.0" -validate-npm-package-license@^3.0.1: +validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== @@ -12148,6 +13919,13 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" +validate-npm-package-name@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz#f16afd48318e6f90a1ec101377fa0384cfc8c713" + integrity sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ== + dependencies: + builtins "^5.0.0" + valtio@1.11.2: version "1.11.2" resolved "https://registry.yarnpkg.com/valtio/-/valtio-1.11.2.tgz#b8049c02dfe65620635d23ebae9121a741bb6530" @@ -12224,20 +14002,6 @@ viem@^1.0.0, viem@^1.1.4, viem@^1.12.2: isows "1.0.3" ws "8.13.0" -viem@^2.7.1: - version "2.9.0" - resolved "https://registry.yarnpkg.com/viem/-/viem-2.9.0.tgz#f59cd9b44d07ceaeacfd33477f116274860fd35d" - integrity sha512-7jNrY9GY4aLGU2qX4/TCXpA9qR4PDx5ctQyJpxoh8jDmlV0Rh2FLlnJsgJs9sAB8cKbNafkRTYQtuMA3OOn0JA== - dependencies: - "@adraffy/ens-normalize" "1.10.0" - "@noble/curves" "1.2.0" - "@noble/hashes" "1.3.2" - "@scure/bip32" "1.3.2" - "@scure/bip39" "1.2.1" - abitype "1.0.0" - isows "1.0.3" - ws "8.13.0" - viem@^2.7.12, viem@^2.7.14, viem@^2.7.8: version "2.8.18" resolved "https://registry.yarnpkg.com/viem/-/viem-2.8.18.tgz#ffb051bf80381ffefc98087a20c177b25463c9f4" @@ -12263,6 +14027,15 @@ vite-node@^1.2.0: picocolors "^1.0.0" vite "^5.0.0" +vite-tsconfig-paths@^4.2.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/vite-tsconfig-paths/-/vite-tsconfig-paths-4.3.2.tgz#321f02e4b736a90ff62f9086467faf4e2da857a9" + integrity sha512-0Vd/a6po6Q+86rPlntHye7F31zA2URZMbH8M3saAZ/xR9QoGN/L21bxEGfXdWmFdNkqPpRdxFT7nmNe12e9/uA== + dependencies: + debug "^4.1.1" + globrex "^0.1.2" + tsconfck "^3.0.3" + vite@^5.0.0, vite@^5.0.11, vite@^5.0.2: version "5.2.3" resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.3.tgz#198efc2fd4d80eac813b146a68a4b0dbde884fc2" @@ -12274,6 +14047,17 @@ vite@^5.0.0, vite@^5.0.11, vite@^5.0.2: optionalDependencies: fsevents "~2.3.3" +vite@^5.1.0: + version "5.2.6" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.6.tgz#fc2ce309e0b4871e938cb0aca3b96c422c01f222" + integrity sha512-FPtnxFlSIKYjZ2eosBQamz4CbyrTizbZ3hnGJlh/wMtCrlp1Hah6AzBLjGI5I2urTfNnpovpHdrL6YRuBOPnCA== + dependencies: + esbuild "^0.20.1" + postcss "^8.4.36" + rollup "^4.13.0" + optionalDependencies: + fsevents "~2.3.3" + vocs@1.0.0-alpha.42: version "1.0.0-alpha.42" resolved "https://registry.yarnpkg.com/vocs/-/vocs-1.0.0-alpha.42.tgz#92a594cdeee41e39d4250adefed10323ff587d3d" @@ -12503,6 +14287,24 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +which@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/which/-/which-3.0.1.tgz#89f1cd0c23f629a8105ffe69b8172791c87b4be1" + integrity sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg== + dependencies: + isexe "^2.0.0" + +workerd@1.20240320.1: + version "1.20240320.1" + resolved "https://registry.yarnpkg.com/workerd/-/workerd-1.20240320.1.tgz#f959a4805bf3bdbdf86d123482132fa30a3f34c9" + integrity sha512-nuavAGGjh0qqM6RF5zxTHyUwEqdLCHchodbrpbh/xlJpFGnJVY5C1YgSi2S9aLkJJoa0/25Ta/+EzXEbApA/3w== + optionalDependencies: + "@cloudflare/workerd-darwin-64" "1.20240320.1" + "@cloudflare/workerd-darwin-arm64" "1.20240320.1" + "@cloudflare/workerd-linux-64" "1.20240320.1" + "@cloudflare/workerd-linux-arm64" "1.20240320.1" + "@cloudflare/workerd-windows-64" "1.20240320.1" + "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -12548,11 +14350,16 @@ ws@8.13.0: resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== -ws@^7.5.1: +ws@^7.4.5, ws@^7.5.1: version "7.5.9" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== +ws@^8.11.0: + version "8.16.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4" + integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ== + ws@~8.11.0: version "8.11.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" @@ -12563,7 +14370,7 @@ xmlhttprequest-ssl@~2.0.0: resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz#91360c86b914e67f44dce769180027c0da618c67" integrity sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A== -xtend@^4.0.1: +xtend@^4.0.1, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== @@ -12656,6 +14463,20 @@ yoga-wasm-web@0.3.3, yoga-wasm-web@^0.3.3: resolved "https://registry.yarnpkg.com/yoga-wasm-web/-/yoga-wasm-web-0.3.3.tgz#eb8e9fcb18e5e651994732f19a220cb885d932ba" integrity sha512-N+d4UJSJbt/R3wqY7Coqs5pcV0aUj2j9IaQ3rNj9bVCLld8tTGKRa2USARjnvZJWVx1NDmQev8EknoczaOQDOA== +youch@^3.2.2: + version "3.3.3" + resolved "https://registry.yarnpkg.com/youch/-/youch-3.3.3.tgz#50cfdf5bc395ce664a5073e31b712ff4a859d928" + integrity sha512-qSFXUk3UZBLfggAW3dJKg0BMblG5biqSF8M34E06o5CSsZtH92u9Hqmj2RzGiHDi64fhe83+4tENFP2DB6t6ZA== + dependencies: + cookie "^0.5.0" + mustache "^4.2.0" + stacktracey "^2.1.8" + +zod@^3.20.6: + version "3.22.4" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff" + integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg== + zustand@4.4.1: version "4.4.1" resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.4.1.tgz#0cd3a3e4756f21811bd956418fdc686877e8b3b0" From 55fab50e105fd2eab89eabd410e14dd1b62c586e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kvasnic=CC=8Ca=CC=81k?= Date: Tue, 26 Mar 2024 10:24:36 +0100 Subject: [PATCH 12/42] chore: docs use code block and revert initial command --- docs/pages/index.mdx | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/docs/pages/index.mdx b/docs/pages/index.mdx index 2dfefd0a2..d91135701 100644 --- a/docs/pages/index.mdx +++ b/docs/pages/index.mdx @@ -7,7 +7,7 @@ import { HomePage } from "vocs/components";

frames.js

- + **frames.js** is the fastest way to make Frames. @@ -41,24 +41,22 @@ import { HomePage } from "vocs/components"; Run one of the commands below based on your preferred package manager and then follow the steps in the terminal. -### Using npm +:::code-group -```sh +```bash [npm] npm init frames ``` -### Using yarn - -```sh +```bash [yarn] yarn create frames ``` -### Using pnpm - -```sh +```bash [pnpm] pnpm create frames ``` +::: + ## Alternatively, add frames.js to your existing project manually ### Start with frames.js in Next.js in three steps @@ -76,7 +74,12 @@ export async function generateMetadata() { return { title: "My page", other: await fetchMetadata( - new URL("/frames", process.env.VERCEL_URL ? `https://${process.env.VERCEL_URL}` : "http://localhost:3000") + new URL( + "/frames", + process.env.VERCEL_URL + ? `https://${process.env.VERCEL_URL}` + : "http://localhost:3000" + ) ), }; } From e1cc93849e88a4ef41cea7972b22dffe93c908f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kvasnic=CC=8Ca=CC=81k?= Date: Tue, 26 Mar 2024 16:21:11 +0100 Subject: [PATCH 13/42] build: do not lint/build templates --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index ce7b4f147..9ac3e3b6b 100644 --- a/package.json +++ b/package.json @@ -3,12 +3,12 @@ "private": true, "scripts": { "build": "turbo build --filter=!./templates/* && node ./.scripts/prepare-create-frames.js", - "build:ci": "turbo build --filter=!debugger --filter=!framesjs-starter --filter=!utils-starter --filter=!docs", + "build:ci": "turbo build --filter=!debugger --filter=!framesjs-starter --filter=!utils-starter --filter=!docs --filter=!template-*", "dev": "FJS_MONOREPO=true turbo dev --filter=framesjs-starter... --filter=debugger...", "dev:custom-redirects": "turbo dev --filter=custom-redirects...", "dev:utils-starter": "turbo dev --filter=utils-starter...", "dev:all": "turbo dev", - "lint": "turbo lint", + "lint": "turbo lint --filter=!template-*", "test:ci": "jest --ci", "test": "cd ./packages/frames.js && npm run test:watch", "publish-packages": "turbo run build lint && changeset version && changeset publish && git push --follow-tags origin main", From e5674d6d42a0cb3f4c6c3e97df201b5930f86b90 Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Tue, 26 Mar 2024 17:25:47 +0200 Subject: [PATCH 14/42] feat: custom middleware example --- .changeset/yellow-zoos-promise.md | 5 +++ .../frames/frames.ts | 27 +++++++++++++++ .../frames/route.tsx | 13 ++++++++ .../new-api-custom-middleware/page.tsx | 33 +++++++++++++++++++ 4 files changed, 78 insertions(+) create mode 100644 .changeset/yellow-zoos-promise.md create mode 100644 examples/framesjs-starter/app/examples/new-api-custom-middleware/frames/frames.ts create mode 100644 examples/framesjs-starter/app/examples/new-api-custom-middleware/frames/route.tsx create mode 100644 examples/framesjs-starter/app/examples/new-api-custom-middleware/page.tsx diff --git a/.changeset/yellow-zoos-promise.md b/.changeset/yellow-zoos-promise.md new file mode 100644 index 000000000..d5c8331fd --- /dev/null +++ b/.changeset/yellow-zoos-promise.md @@ -0,0 +1,5 @@ +--- +"framesjs-starter": patch +--- + +feat: custom middleware example diff --git a/examples/framesjs-starter/app/examples/new-api-custom-middleware/frames/frames.ts b/examples/framesjs-starter/app/examples/new-api-custom-middleware/frames/frames.ts new file mode 100644 index 000000000..eee185c92 --- /dev/null +++ b/examples/framesjs-starter/app/examples/new-api-custom-middleware/frames/frames.ts @@ -0,0 +1,27 @@ +import { createFrames, types } from "frames.js/next"; + +const priceMiddleware: types.FramesMiddleware< + any, + { ethPrice?: number } +> = async (ctx, next) => { + try { + const res = await fetch( + "https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd" + ); + const { + ethereum: { usd: ethPrice }, + } = await res.json(); + return next({ ethPrice }); + } catch (error) { + console.error("Error fetching ETH price:", error); + } + return next(); +}; + +export const frames = createFrames({ + basePath: "/", + initialState: { + pageIndex: 0, + }, + middleware: [priceMiddleware], +}); diff --git a/examples/framesjs-starter/app/examples/new-api-custom-middleware/frames/route.tsx b/examples/framesjs-starter/app/examples/new-api-custom-middleware/frames/route.tsx new file mode 100644 index 000000000..c977e2192 --- /dev/null +++ b/examples/framesjs-starter/app/examples/new-api-custom-middleware/frames/route.tsx @@ -0,0 +1,13 @@ +/* eslint-disable react/jsx-key */ +import { Button } from "frames.js/next"; +import { frames } from "./frames"; + +const handler = frames(async (ctx) => { + return { + image:
ETH price: ${ctx.ethPrice}
, + buttons: [], + }; +}); + +export const GET = handler; +export const POST = handler; diff --git a/examples/framesjs-starter/app/examples/new-api-custom-middleware/page.tsx b/examples/framesjs-starter/app/examples/new-api-custom-middleware/page.tsx new file mode 100644 index 000000000..9626a3189 --- /dev/null +++ b/examples/framesjs-starter/app/examples/new-api-custom-middleware/page.tsx @@ -0,0 +1,33 @@ +import Link from "next/link"; +import { currentURL, vercelURL } from "../../utils"; +import { createDebugUrl } from "../../debug"; +import type { Metadata } from "next"; +import { fetchMetadata } from "frames.js/next"; + +export async function generateMetadata(): Promise { + return { + title: "New api example", + description: "This is a new api example", + other: { + ...(await fetchMetadata( + new URL( + "/examples/new-api-custom-middleware/frames", + vercelURL() || "http://localhost:3000" + ) + )), + }, + }; +} + +export default async function Home() { + const url = currentURL("/examples/new-api-cache-control"); + + return ( +
+ Custom middleware example{" "} + + Debug + +
+ ); +} From 29bcbc623c29faff271c100b35c16c5680eddc49 Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Tue, 26 Mar 2024 21:22:24 +0200 Subject: [PATCH 15/42] fix(nextjs): prioritize APP_URL over VERCEL_URL --- .changeset/new-moose-talk.md | 5 +++++ packages/frames.js/src/next/getCurrentUrl.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/new-moose-talk.md diff --git a/.changeset/new-moose-talk.md b/.changeset/new-moose-talk.md new file mode 100644 index 000000000..c90a06f49 --- /dev/null +++ b/.changeset/new-moose-talk.md @@ -0,0 +1,5 @@ +--- +"frames.js": patch +--- + +fix(nextjs): prioritize APP_URL over VERCEL_URL diff --git a/packages/frames.js/src/next/getCurrentUrl.ts b/packages/frames.js/src/next/getCurrentUrl.ts index e979da50e..fcf35c982 100644 --- a/packages/frames.js/src/next/getCurrentUrl.ts +++ b/packages/frames.js/src/next/getCurrentUrl.ts @@ -6,7 +6,7 @@ export function getCurrentUrl( req: Request | NextRequest | NextApiRequest | IncomingMessage ): URL | undefined { const scheme = process.env.NODE_ENV === "production" ? "https://" : "http://"; - const appUrl = process.env.VERCEL_URL || process.env.APP_URL; + const appUrl = process.env.APP_URL || process.env.VERCEL_URL; const host: string | undefined = (req.headers as any)?.host; const pathname = req.url?.startsWith("/") From 8800afafd113236849dc78f583bd39563242d5e1 Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Wed, 27 Mar 2024 10:54:31 +0200 Subject: [PATCH 16/42] feat: updated multi-page example --- .changeset/ten-beans-compete.md | 5 ++ .../new-api-multi-page/frames/frames.ts | 5 ++ .../new-api-multi-page/frames/route.tsx | 46 +++++-------------- .../frames/route1/route.tsx | 19 ++++++++ .../frames/route2/route.tsx | 20 ++++++++ 5 files changed, 61 insertions(+), 34 deletions(-) create mode 100644 .changeset/ten-beans-compete.md create mode 100644 examples/framesjs-starter/app/examples/new-api-multi-page/frames/frames.ts create mode 100644 examples/framesjs-starter/app/examples/new-api-multi-page/frames/route1/route.tsx create mode 100644 examples/framesjs-starter/app/examples/new-api-multi-page/frames/route2/route.tsx diff --git a/.changeset/ten-beans-compete.md b/.changeset/ten-beans-compete.md new file mode 100644 index 000000000..6ea64ca77 --- /dev/null +++ b/.changeset/ten-beans-compete.md @@ -0,0 +1,5 @@ +--- +"framesjs-starter": patch +--- + +feat: updated multi-page example diff --git a/examples/framesjs-starter/app/examples/new-api-multi-page/frames/frames.ts b/examples/framesjs-starter/app/examples/new-api-multi-page/frames/frames.ts new file mode 100644 index 000000000..4387effc7 --- /dev/null +++ b/examples/framesjs-starter/app/examples/new-api-multi-page/frames/frames.ts @@ -0,0 +1,5 @@ +import { createFrames } from "frames.js/next"; + +export const frames = createFrames({ + basePath: "/examples/new-api-multi-page/frames", +}); diff --git a/examples/framesjs-starter/app/examples/new-api-multi-page/frames/route.tsx b/examples/framesjs-starter/app/examples/new-api-multi-page/frames/route.tsx index 8973e65f0..8b50f41d3 100644 --- a/examples/framesjs-starter/app/examples/new-api-multi-page/frames/route.tsx +++ b/examples/framesjs-starter/app/examples/new-api-multi-page/frames/route.tsx @@ -1,47 +1,25 @@ /* eslint-disable react/jsx-key */ -import { createFrames, Button } from "frames.js/next"; - -const totalPages = 5; - -const frames = createFrames({ - basePath: "/examples/new-api-multi-page/frames", -}); - -const handleRequest = frames(async (ctx) => { - const pageIndex = Number(ctx.searchParams.pageIndex || 0); - - const imageUrl = `https://picsum.photos/seed/frames.js-${pageIndex}/300/200`; +import { frames } from "./frames"; +import { Button } from "frames.js/next"; +const handler = frames(async () => { return { - image: ( -
- Image -
- This is slide {pageIndex + 1} / {totalPages} -
-
- ), + image:
Welcome
, buttons: [ + // With query params , - , ], - textInput: "Type something!", }; }); -export const GET = handleRequest; -export const POST = handleRequest; +export const GET = handler; +export const POST = handler; diff --git a/examples/framesjs-starter/app/examples/new-api-multi-page/frames/route1/route.tsx b/examples/framesjs-starter/app/examples/new-api-multi-page/frames/route1/route.tsx new file mode 100644 index 000000000..e9e360619 --- /dev/null +++ b/examples/framesjs-starter/app/examples/new-api-multi-page/frames/route1/route.tsx @@ -0,0 +1,19 @@ +/* eslint-disable react/jsx-key */ +import { frames } from "../frames"; +import { Button } from "frames.js/next"; + +export const POST = frames(async (ctx) => { + const foo = ctx.searchParams.foo; + + return { + image:
Route 1 foo: {foo}
, // foo: bar + buttons: [ + , + , + ], + }; +}); diff --git a/examples/framesjs-starter/app/examples/new-api-multi-page/frames/route2/route.tsx b/examples/framesjs-starter/app/examples/new-api-multi-page/frames/route2/route.tsx new file mode 100644 index 000000000..bad5c0c45 --- /dev/null +++ b/examples/framesjs-starter/app/examples/new-api-multi-page/frames/route2/route.tsx @@ -0,0 +1,20 @@ +/* eslint-disable react/jsx-key */ +import { frames } from "../frames"; +import { Button } from "frames.js/next"; + +export const POST = frames(async () => { + return { + image:
Route 2
, + buttons: [ + , + , + ], + }; +}); From 4451b7c38c9cc7ec542c3bef36b7b70db1a21436 Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Wed, 27 Mar 2024 11:05:52 +0200 Subject: [PATCH 17/42] fix: refactor frames app into frames.ts in examples --- .changeset/thirty-dots-doubt.md | 5 +++++ .../new-api-cache-control/frames/frames.ts | 5 +++++ .../new-api-cache-control/frames/route.tsx | 6 +----- .../examples/new-api-mint-button/frames/frames.ts | 5 +++++ .../examples/new-api-mint-button/frames/route.tsx | 7 ++----- .../new-api-multi-protocol/{ => frames}/frames.ts | 4 ++-- .../new-api-multi-protocol/frames/route.tsx | 2 +- .../{ => frames}/who-am-i/route.tsx | 0 .../frames/frames.ts | 12 ++++++++++++ .../frames/route.tsx | 14 ++------------ .../new-api-post-redirect/frames/frames.ts | 5 +++++ .../new-api-post-redirect/frames/route.tsx | 7 ++----- .../examples/new-api-slow-request/frames/frames.ts | 5 +++++ .../examples/new-api-slow-request/frames/route.tsx | 7 ++----- .../examples/new-api-transaction/frames/frames.ts | 5 +++++ .../examples/new-api-transaction/frames/route.tsx | 6 +----- 16 files changed, 55 insertions(+), 40 deletions(-) create mode 100644 .changeset/thirty-dots-doubt.md create mode 100644 examples/framesjs-starter/app/examples/new-api-cache-control/frames/frames.ts create mode 100644 examples/framesjs-starter/app/examples/new-api-mint-button/frames/frames.ts rename examples/framesjs-starter/app/examples/new-api-multi-protocol/{ => frames}/frames.ts (88%) rename examples/framesjs-starter/app/examples/new-api-multi-protocol/{ => frames}/who-am-i/route.tsx (100%) create mode 100644 examples/framesjs-starter/app/examples/new-api-only-followers-can-mint/frames/frames.ts create mode 100644 examples/framesjs-starter/app/examples/new-api-post-redirect/frames/frames.ts create mode 100644 examples/framesjs-starter/app/examples/new-api-slow-request/frames/frames.ts create mode 100644 examples/framesjs-starter/app/examples/new-api-transaction/frames/frames.ts diff --git a/.changeset/thirty-dots-doubt.md b/.changeset/thirty-dots-doubt.md new file mode 100644 index 000000000..4fa25c547 --- /dev/null +++ b/.changeset/thirty-dots-doubt.md @@ -0,0 +1,5 @@ +--- +"framesjs-starter": patch +--- + +fix: refactor frames app into frames.ts in examples diff --git a/examples/framesjs-starter/app/examples/new-api-cache-control/frames/frames.ts b/examples/framesjs-starter/app/examples/new-api-cache-control/frames/frames.ts new file mode 100644 index 000000000..fe4ae3f1e --- /dev/null +++ b/examples/framesjs-starter/app/examples/new-api-cache-control/frames/frames.ts @@ -0,0 +1,5 @@ +import { createFrames } from "frames.js/next"; + +export const frames = createFrames({ + basePath: "/examples/new-api-cache-control", +}); diff --git a/examples/framesjs-starter/app/examples/new-api-cache-control/frames/route.tsx b/examples/framesjs-starter/app/examples/new-api-cache-control/frames/route.tsx index ee6293fa3..0b8a89e6f 100644 --- a/examples/framesjs-starter/app/examples/new-api-cache-control/frames/route.tsx +++ b/examples/framesjs-starter/app/examples/new-api-cache-control/frames/route.tsx @@ -1,10 +1,6 @@ /* eslint-disable react/jsx-key */ import { Button } from "frames.js/next"; -import { createFrames } from "frames.js/next"; - -const frames = createFrames({ - basePath: "/examples/new-api-cache-control", -}); +import { frames } from "./frames"; const handleRequest = frames(async (ctx) => { return { diff --git a/examples/framesjs-starter/app/examples/new-api-mint-button/frames/frames.ts b/examples/framesjs-starter/app/examples/new-api-mint-button/frames/frames.ts new file mode 100644 index 000000000..94b797cf6 --- /dev/null +++ b/examples/framesjs-starter/app/examples/new-api-mint-button/frames/frames.ts @@ -0,0 +1,5 @@ +import { createFrames } from "frames.js/next"; + +export const frames = createFrames({ + basePath: "/examples/new-api-mint-button/frames", +}); diff --git a/examples/framesjs-starter/app/examples/new-api-mint-button/frames/route.tsx b/examples/framesjs-starter/app/examples/new-api-mint-button/frames/route.tsx index 23ee9ccf8..5221bbf65 100644 --- a/examples/framesjs-starter/app/examples/new-api-mint-button/frames/route.tsx +++ b/examples/framesjs-starter/app/examples/new-api-mint-button/frames/route.tsx @@ -1,7 +1,8 @@ /* eslint-disable react/jsx-key */ -import { Button, createFrames } from "frames.js/next"; +import { Button } from "frames.js/next"; import { getTokenUrl } from "frames.js"; import { zora } from "viem/chains"; +import { frames } from "./frames"; const nfts: { src: string; @@ -33,10 +34,6 @@ const nfts: { }, ]; -const frames = createFrames({ - basePath: "/examples/new-api-mint-button/frames", -}); - const handleRequest = frames(async (ctx) => { const page = Number(ctx.searchParams?.pageIndex ?? 0); return { diff --git a/examples/framesjs-starter/app/examples/new-api-multi-protocol/frames.ts b/examples/framesjs-starter/app/examples/new-api-multi-protocol/frames/frames.ts similarity index 88% rename from examples/framesjs-starter/app/examples/new-api-multi-protocol/frames.ts rename to examples/framesjs-starter/app/examples/new-api-multi-protocol/frames/frames.ts index 0234c8657..0b9fea07f 100644 --- a/examples/framesjs-starter/app/examples/new-api-multi-protocol/frames.ts +++ b/examples/framesjs-starter/app/examples/new-api-multi-protocol/frames/frames.ts @@ -2,10 +2,10 @@ import { farcasterHubContext, openframes } from "frames.js/middleware"; import { createFrames } from "frames.js/next"; import { getXmtpFrameMessage, isXmtpFrameActionPayload } from "frames.js/xmtp"; -import { DEFAULT_DEBUGGER_HUB_URL } from "../../debug"; +import { DEFAULT_DEBUGGER_HUB_URL } from "../../../debug"; export const frames = createFrames({ - basePath: "/examples/new-api-multi-protocol", + basePath: "/examples/new-api-multi-protocol/frames", initialState: { pageIndex: 0, }, diff --git a/examples/framesjs-starter/app/examples/new-api-multi-protocol/frames/route.tsx b/examples/framesjs-starter/app/examples/new-api-multi-protocol/frames/route.tsx index 07043b99d..e0aa09916 100644 --- a/examples/framesjs-starter/app/examples/new-api-multi-protocol/frames/route.tsx +++ b/examples/framesjs-starter/app/examples/new-api-multi-protocol/frames/route.tsx @@ -1,5 +1,5 @@ import { Button } from "frames.js/next"; -import { frames } from "../frames"; +import { frames } from "./frames"; const handleRequest = frames(async (ctx) => { return { diff --git a/examples/framesjs-starter/app/examples/new-api-multi-protocol/who-am-i/route.tsx b/examples/framesjs-starter/app/examples/new-api-multi-protocol/frames/who-am-i/route.tsx similarity index 100% rename from examples/framesjs-starter/app/examples/new-api-multi-protocol/who-am-i/route.tsx rename to examples/framesjs-starter/app/examples/new-api-multi-protocol/frames/who-am-i/route.tsx diff --git a/examples/framesjs-starter/app/examples/new-api-only-followers-can-mint/frames/frames.ts b/examples/framesjs-starter/app/examples/new-api-only-followers-can-mint/frames/frames.ts new file mode 100644 index 000000000..38920546f --- /dev/null +++ b/examples/framesjs-starter/app/examples/new-api-only-followers-can-mint/frames/frames.ts @@ -0,0 +1,12 @@ +import { farcasterHubContext } from "frames.js/middleware"; +import { createFrames } from "frames.js/next"; +import { DEFAULT_DEBUGGER_HUB_URL } from "../../../debug"; + +export const frames = createFrames({ + basePath: "/examples/new-api-only-followers-can-mint/frames", + middleware: [ + farcasterHubContext({ + hubHttpUrl: DEFAULT_DEBUGGER_HUB_URL, + }), + ], +}); diff --git a/examples/framesjs-starter/app/examples/new-api-only-followers-can-mint/frames/route.tsx b/examples/framesjs-starter/app/examples/new-api-only-followers-can-mint/frames/route.tsx index 31cc4f6a5..2a91ba277 100644 --- a/examples/framesjs-starter/app/examples/new-api-only-followers-can-mint/frames/route.tsx +++ b/examples/framesjs-starter/app/examples/new-api-only-followers-can-mint/frames/route.tsx @@ -1,18 +1,8 @@ /* eslint-disable react/jsx-key */ import { getTokenUrl } from "frames.js"; -import { farcasterHubContext } from "frames.js/middleware"; -import { Button, createFrames } from "frames.js/next"; +import { Button } from "frames.js/next"; import { zora } from "viem/chains"; -import { DEFAULT_DEBUGGER_HUB_URL } from "../../../debug"; - -const frames = createFrames({ - basePath: "/examples/new-api-only-followers-can-mint/frames", - middleware: [ - farcasterHubContext({ - hubHttpUrl: DEFAULT_DEBUGGER_HUB_URL, - }), - ], -}); +import { frames } from "./frames"; const handleRequest = frames(async (ctx) => { const page = ctx.searchParams?.page ?? "initial"; diff --git a/examples/framesjs-starter/app/examples/new-api-post-redirect/frames/frames.ts b/examples/framesjs-starter/app/examples/new-api-post-redirect/frames/frames.ts new file mode 100644 index 000000000..a5a37a0d6 --- /dev/null +++ b/examples/framesjs-starter/app/examples/new-api-post-redirect/frames/frames.ts @@ -0,0 +1,5 @@ +import { createFrames } from "frames.js/next"; + +export const frames = createFrames({ + basePath: "/examples/new-api-post-redirect/frames", +}); diff --git a/examples/framesjs-starter/app/examples/new-api-post-redirect/frames/route.tsx b/examples/framesjs-starter/app/examples/new-api-post-redirect/frames/route.tsx index b478f04b1..c80484e74 100644 --- a/examples/framesjs-starter/app/examples/new-api-post-redirect/frames/route.tsx +++ b/examples/framesjs-starter/app/examples/new-api-post-redirect/frames/route.tsx @@ -1,10 +1,7 @@ /* eslint-disable react/jsx-key */ -import { createFrames, Button } from "frames.js/next"; +import { Button } from "frames.js/next"; import { redirect } from "frames.js/core"; - -const frames = createFrames({ - basePath: "/examples/new-api-post-redirect/frames", -}); +import { frames } from "./frames"; const handleRequest = frames(async (ctx) => { if (ctx.pressedButton?.action === "post_redirect") { diff --git a/examples/framesjs-starter/app/examples/new-api-slow-request/frames/frames.ts b/examples/framesjs-starter/app/examples/new-api-slow-request/frames/frames.ts new file mode 100644 index 000000000..5ea7f8d1a --- /dev/null +++ b/examples/framesjs-starter/app/examples/new-api-slow-request/frames/frames.ts @@ -0,0 +1,5 @@ +import { createFrames } from "frames.js/next"; + +export const frames = createFrames({ + basePath: "/examples/new-api-slow-request/frames", +}); diff --git a/examples/framesjs-starter/app/examples/new-api-slow-request/frames/route.tsx b/examples/framesjs-starter/app/examples/new-api-slow-request/frames/route.tsx index a9944f032..b785e1d11 100644 --- a/examples/framesjs-starter/app/examples/new-api-slow-request/frames/route.tsx +++ b/examples/framesjs-starter/app/examples/new-api-slow-request/frames/route.tsx @@ -1,11 +1,8 @@ import { kv } from "@vercel/kv"; import { types } from "frames.js/core"; -import { createFrames, Button } from "frames.js/next"; +import { Button } from "frames.js/next"; import { RandomNumberRequestStateValue } from "../slow-fetch/types"; - -const frames = createFrames({ - basePath: "/examples/new-api-slow-request/frames", -}); +import { frames } from "./frames"; const handleRequest = frames(async (ctx) => { const initialFrame = { diff --git a/examples/framesjs-starter/app/examples/new-api-transaction/frames/frames.ts b/examples/framesjs-starter/app/examples/new-api-transaction/frames/frames.ts new file mode 100644 index 000000000..3a29b360a --- /dev/null +++ b/examples/framesjs-starter/app/examples/new-api-transaction/frames/frames.ts @@ -0,0 +1,5 @@ +import { createFrames } from "frames.js/next"; + +export const frames = createFrames({ + basePath: "/examples/new-api-transaction", +}); diff --git a/examples/framesjs-starter/app/examples/new-api-transaction/frames/route.tsx b/examples/framesjs-starter/app/examples/new-api-transaction/frames/route.tsx index 8a1587891..51e0831cb 100644 --- a/examples/framesjs-starter/app/examples/new-api-transaction/frames/route.tsx +++ b/examples/framesjs-starter/app/examples/new-api-transaction/frames/route.tsx @@ -1,10 +1,6 @@ /* eslint-disable react/jsx-key */ import { Button } from "frames.js/next"; -import { createFrames } from "frames.js/next"; - -const frames = createFrames({ - basePath: "/examples/new-api-transaction", -}); +import { frames } from "./frames"; const handleRequest = frames(async (ctx) => { if (ctx.message?.transactionId) { From 9b5690f89b452a6193429d8de0e9ff0ed2c62187 Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Wed, 27 Mar 2024 12:13:48 +0200 Subject: [PATCH 18/42] feat: custom fonts example --- .changeset/grumpy-moose-beam.md | 5 ++ .../new-api-custom-font/frames/edge/route.tsx | 65 ++++++++++++++++ .../new-api-custom-font/frames/frames.ts | 5 ++ .../frames/nodejs/route.tsx | 71 ++++++++++++++++++ .../new-api-custom-font/frames/route.tsx | 20 +++++ .../app/examples/new-api-custom-font/page.tsx | 33 ++++++++ .../public/FiraCodeiScript-Regular.ttf | Bin 0 -> 242896 bytes .../framesjs-starter/public/Inter-Bold.ttf | Bin 0 -> 316584 bytes 8 files changed, 199 insertions(+) create mode 100644 .changeset/grumpy-moose-beam.md create mode 100644 examples/framesjs-starter/app/examples/new-api-custom-font/frames/edge/route.tsx create mode 100644 examples/framesjs-starter/app/examples/new-api-custom-font/frames/frames.ts create mode 100644 examples/framesjs-starter/app/examples/new-api-custom-font/frames/nodejs/route.tsx create mode 100644 examples/framesjs-starter/app/examples/new-api-custom-font/frames/route.tsx create mode 100644 examples/framesjs-starter/app/examples/new-api-custom-font/page.tsx create mode 100644 examples/framesjs-starter/public/FiraCodeiScript-Regular.ttf create mode 100644 examples/framesjs-starter/public/Inter-Bold.ttf diff --git a/.changeset/grumpy-moose-beam.md b/.changeset/grumpy-moose-beam.md new file mode 100644 index 000000000..b6a51eac8 --- /dev/null +++ b/.changeset/grumpy-moose-beam.md @@ -0,0 +1,5 @@ +--- +"framesjs-starter": patch +--- + +feat: custom fonts example diff --git a/examples/framesjs-starter/app/examples/new-api-custom-font/frames/edge/route.tsx b/examples/framesjs-starter/app/examples/new-api-custom-font/frames/edge/route.tsx new file mode 100644 index 000000000..286509143 --- /dev/null +++ b/examples/framesjs-starter/app/examples/new-api-custom-font/frames/edge/route.tsx @@ -0,0 +1,65 @@ +/* eslint-disable react/jsx-key */ +import { Button } from "frames.js/next"; +import { frames } from "../frames"; + +// without this line, this type of importing fonts doesn't work for some reason +export const runtime = "edge"; + +const interRegularFont = fetch( + new URL("/public/Inter-Regular.ttf", import.meta.url) +).then((res) => res.arrayBuffer()); +const interBoldFont = fetch( + new URL("/public/Inter-Bold.ttf", import.meta.url) +).then((res) => res.arrayBuffer()); +const firaScriptFont = fetch( + new URL("/public/FiraCodeiScript-Regular.ttf", import.meta.url) +).then((res) => res.arrayBuffer()); + +const handleRequest = frames(async (ctx) => { + const [interRegularFontData, interBoldFontData, firaScriptFontData] = + await Promise.all([interRegularFont, interBoldFont, firaScriptFont]); + + return { + image: ( + +
Edge functions example custom fonts
+
Regular Inter Font
+
Bold Inter Font
+
+ Fira +
+
+ ), + buttons: [ + , + ], + imageOptions: { + fonts: [ + { + name: "Inter", + data: interRegularFontData, + weight: 400, + }, + { + name: "Inter", + data: interBoldFontData, + weight: 700, + }, + { + name: "Fira Code", + data: firaScriptFontData, + weight: 700, + }, + ], + }, + }; +}); + +export const POST = handleRequest; diff --git a/examples/framesjs-starter/app/examples/new-api-custom-font/frames/frames.ts b/examples/framesjs-starter/app/examples/new-api-custom-font/frames/frames.ts new file mode 100644 index 000000000..56b6d5e19 --- /dev/null +++ b/examples/framesjs-starter/app/examples/new-api-custom-font/frames/frames.ts @@ -0,0 +1,5 @@ +import { createFrames } from "frames.js/next"; + +export const frames = createFrames({ + basePath: "/examples/new-api-custom-font/frames", +}); diff --git a/examples/framesjs-starter/app/examples/new-api-custom-font/frames/nodejs/route.tsx b/examples/framesjs-starter/app/examples/new-api-custom-font/frames/nodejs/route.tsx new file mode 100644 index 000000000..dce9f01c2 --- /dev/null +++ b/examples/framesjs-starter/app/examples/new-api-custom-font/frames/nodejs/route.tsx @@ -0,0 +1,71 @@ +/* eslint-disable react/jsx-key */ +import { Button } from "frames.js/next"; +import * as fs from "node:fs/promises"; +import * as path from "node:path"; +import { frames } from "../frames"; + +export const runtime = "nodejs"; + +const interRegularFont = fs.readFile( + path.join(path.resolve(process.cwd(), "public"), "Inter-Regular.ttf") +); + +const interBoldFont = fs.readFile( + path.join(path.resolve(process.cwd(), "public"), "Inter-Bold.ttf") +); + +const firaScriptFont = fs.readFile( + path.join( + path.resolve(process.cwd(), "public"), + "FiraCodeiScript-Regular.ttf" + ) +); + +const handleRequest = frames(async (ctx) => { + const [interRegularFontData, interBoldFontData, firaScriptData] = + await Promise.all([interRegularFont, interBoldFont, firaScriptFont]); + + return { + buttons: [ + , + ], + image: ( + +
Node.js example custom fonts
+
Regular Inter Font
+
Bold Inter Font
+
+ Fira +
+
+ ), + imageOptions: { + fonts: [ + { + name: "Inter", + data: interRegularFontData, + weight: 400, + }, + { + name: "Inter", + data: interBoldFontData, + weight: 700, + }, + { + name: "Fira Code", + data: firaScriptData, + weight: 700, + }, + ], + }, + }; +}); + +export const POST = handleRequest; diff --git a/examples/framesjs-starter/app/examples/new-api-custom-font/frames/route.tsx b/examples/framesjs-starter/app/examples/new-api-custom-font/frames/route.tsx new file mode 100644 index 000000000..f0e6336b1 --- /dev/null +++ b/examples/framesjs-starter/app/examples/new-api-custom-font/frames/route.tsx @@ -0,0 +1,20 @@ +/* eslint-disable react/jsx-key */ +import { Button } from "frames.js/next"; +import { frames } from "./frames"; + +const handler = frames(async (ctx) => { + return { + image:
Custom fonts example
, + buttons: [ + , + , + ], + }; +}); + +export const GET = handler; +export const POST = handler; diff --git a/examples/framesjs-starter/app/examples/new-api-custom-font/page.tsx b/examples/framesjs-starter/app/examples/new-api-custom-font/page.tsx new file mode 100644 index 000000000..037c78484 --- /dev/null +++ b/examples/framesjs-starter/app/examples/new-api-custom-font/page.tsx @@ -0,0 +1,33 @@ +import Link from "next/link"; +import { currentURL, vercelURL } from "../../utils"; +import { createDebugUrl } from "../../debug"; +import type { Metadata } from "next"; +import { fetchMetadata } from "frames.js/next"; + +export async function generateMetadata(): Promise { + return { + title: "New api example", + description: "This is a new api example", + other: { + ...(await fetchMetadata( + new URL( + "/examples/new-api-custom-font/frames", + vercelURL() || "http://localhost:3000" + ) + )), + }, + }; +} + +export default async function Home() { + const url = currentURL("/examples/new-api-custom-font"); + + return ( +
+ Custom font example{" "} + + Debug + +
+ ); +} diff --git a/examples/framesjs-starter/public/FiraCodeiScript-Regular.ttf b/examples/framesjs-starter/public/FiraCodeiScript-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..b63a44681b367594552343d0ef8c2ab5a3203044 GIT binary patch literal 242896 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 literal 0 HcmV?d00001 diff --git a/examples/framesjs-starter/public/Inter-Bold.ttf b/examples/framesjs-starter/public/Inter-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..fe23eeb9c93a377d0f4ab003f1f77b555d19b1d1 GIT binary patch literal 316584 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 #OJ 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ȇ@(g~$ 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 literal 0 HcmV?d00001 From e017466382f4286e1e0904a4f473e249e1d41517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kvasnic=CC=8Ca=CC=81k?= Date: Wed, 27 Mar 2024 12:40:29 +0100 Subject: [PATCH 19/42] fix: correctly tree shake bundle --- packages/frames.js/package.json | 4 +- packages/frames.js/src/core/types.ts | 2 +- packages/frames.js/src/getAddressForFid.ts | 4 +- packages/frames.js/src/getAddressesForFid.ts | 4 +- packages/frames.js/src/getFrameMessage.ts | 16 +-- packages/frames.js/src/hono/index.ts | 2 +- .../renderResponse.test.tsx.snap | 112 ++++++++++-------- .../frames.js/src/middleware/farcaster.ts | 9 +- .../src/middleware/farcasterHubContext.ts | 10 +- .../src/middleware/framesjsMiddleware.ts | 2 +- .../frames.js/src/middleware/openframes.ts | 7 +- .../{renderResponse.tsx => renderResponse.ts} | 58 +++++---- .../src/middleware/stateMiddleware.ts | 2 +- packages/frames.js/src/next/fetchMetadata.ts | 4 +- packages/frames.js/src/next/index.ts | 2 +- packages/frames.js/src/next/pages-router.tsx | 2 +- packages/frames.js/src/next/server.tsx | 14 +-- packages/frames.js/src/next/types.ts | 2 +- packages/frames.js/src/remix/fetchMetadata.ts | 2 +- packages/frames.js/src/remix/index.ts | 2 +- packages/frames.js/src/types.ts | 2 +- packages/frames.js/src/utils.ts | 2 +- .../frames.js/src/validateFrameMessage.ts | 9 +- packages/frames.js/tsup.config.ts | 15 +++ packages/render/package.json | 4 +- packages/render/tsup.config.ts | 15 +++ 26 files changed, 177 insertions(+), 130 deletions(-) rename packages/frames.js/src/middleware/{renderResponse.tsx => renderResponse.ts} (90%) create mode 100644 packages/frames.js/tsup.config.ts create mode 100644 packages/render/tsup.config.ts diff --git a/packages/frames.js/package.json b/packages/frames.js/package.json index d1e16aca6..36864a2c6 100644 --- a/packages/frames.js/package.json +++ b/packages/frames.js/package.json @@ -14,7 +14,7 @@ }, "scripts": { "lint": "eslint \"./src/**/*.{ts,tsx}\"", - "build": "NODE_OPTIONS='--max-old-space-size=16384' tsup `find ./src -type f \\( -regex '.*\\.tsx*' -a -not -regex '.*\\.test\\.tsx*' \\)` --format cjs,esm --dts", + "build": "NODE_OPTIONS='--max-old-space-size=16384' tsup", "dev": "npm run build -- --watch", "test:watch": "jest --watch", "update:proto": "curl https://raw.githubusercontent.com/farcasterxyz/hub-monorepo/main/packages/core/src/protobufs/generated/message.ts -o src/farcaster/generated/message.ts" @@ -236,4 +236,4 @@ "protobufjs": "^7.2.6", "viem": "^2.7.8" } -} \ No newline at end of file +} diff --git a/packages/frames.js/src/core/types.ts b/packages/frames.js/src/core/types.ts index 2d031ab4e..07f819469 100644 --- a/packages/frames.js/src/core/types.ts +++ b/packages/frames.js/src/core/types.ts @@ -1,5 +1,5 @@ import { ImageResponse } from "@vercel/og"; -import { ClientProtocolId } from ".."; +import type { ClientProtocolId } from "../types"; import { Button } from "./components"; export type JsonObject = { [Key in string]: JsonValue } & { diff --git a/packages/frames.js/src/getAddressForFid.ts b/packages/frames.js/src/getAddressForFid.ts index 9ef467662..ef0b2005d 100644 --- a/packages/frames.js/src/getAddressForFid.ts +++ b/packages/frames.js/src/getAddressForFid.ts @@ -1,8 +1,8 @@ import { createPublicClient, http, parseAbi } from "viem"; import { optimism } from "viem/chains"; -import { AddressReturnType, HubHttpUrlOptions } from "./types"; +import type { AddressReturnType, HubHttpUrlOptions } from "./types"; import { DEFAULT_HUB_API_KEY, DEFAULT_HUB_API_URL } from "./default"; -import { extractAddressFromJSONMessage } from "."; +import { extractAddressFromJSONMessage } from "./utils"; /** * Returns the first verified address for a given `Farcaster` users `fid` if available, falling back to their account custodyAddress diff --git a/packages/frames.js/src/getAddressesForFid.ts b/packages/frames.js/src/getAddressesForFid.ts index 1852113fd..a6f5369e1 100644 --- a/packages/frames.js/src/getAddressesForFid.ts +++ b/packages/frames.js/src/getAddressesForFid.ts @@ -1,8 +1,8 @@ import { createPublicClient, http, parseAbi } from "viem"; import { optimism } from "viem/chains"; -import { AddressWithType, HubHttpUrlOptions } from "./types"; +import type { AddressWithType, HubHttpUrlOptions } from "./types"; import { DEFAULT_HUB_API_KEY, DEFAULT_HUB_API_URL } from "./default"; -import { extractAddressFromJSONMessage } from "."; +import { extractAddressFromJSONMessage } from "./utils"; async function getCustodyAddressForFid(fid: number): Promise { const publicClient = createPublicClient({ diff --git a/packages/frames.js/src/getFrameMessage.ts b/packages/frames.js/src/getFrameMessage.ts index 4708fc5a9..f0a4bf1d6 100644 --- a/packages/frames.js/src/getFrameMessage.ts +++ b/packages/frames.js/src/getFrameMessage.ts @@ -1,16 +1,16 @@ -import { FrameActionMessage, Message } from "./farcaster"; -import { bytesToHex } from "viem"; -import { +import { type FrameActionMessage, Message } from "./farcaster"; +import { bytesToHex } from "viem/utils"; +import { normalizeCastId } from "./utils"; +import type { FrameActionDataParsed, FrameActionDataParsedAndHubContext, FrameActionHubContext, FrameActionPayload, HubHttpUrlOptions, - getAddressesForFid, - getUserDataForFid, - normalizeCastId, - validateFrameMessage, -} from "."; +} from "./types"; +import { getAddressesForFid } from "./getAddressesForFid"; +import { getUserDataForFid } from "./getUserDataForFid"; +import { validateFrameMessage } from "./validateFrameMessage"; import { DEFAULT_HUB_API_KEY, DEFAULT_HUB_API_URL } from "./default"; export type GetFrameMessageOptions = { diff --git a/packages/frames.js/src/hono/index.ts b/packages/frames.js/src/hono/index.ts index 8ec53110d..f580d6f4c 100644 --- a/packages/frames.js/src/hono/index.ts +++ b/packages/frames.js/src/hono/index.ts @@ -13,7 +13,7 @@ type CreateFramesForHono = types.CreateFramesFunctionDefinition< * * @example * import { createFrames, Button } from 'frames.js/hono'; - * import { Honoe } from 'hono'; + * import { Hono } from 'hono'; * * const frames = createFrames(); * const honoHandler = frames(async (ctx) => { diff --git a/packages/frames.js/src/middleware/__snapshots__/renderResponse.test.tsx.snap b/packages/frames.js/src/middleware/__snapshots__/renderResponse.test.tsx.snap index 24f21f3d7..1338b4373 100644 --- a/packages/frames.js/src/middleware/__snapshots__/renderResponse.test.tsx.snap +++ b/packages/frames.js/src/middleware/__snapshots__/renderResponse.test.tsx.snap @@ -5,73 +5,81 @@ exports[`renderResponse middleware allows to render a frame as json if Accept he exports[`renderResponse middleware allows to render a frame with image defined as react element 1`] = `""`; exports[`renderResponse middleware correctly renders image wich conditional content 1`] = ` -

+ Something is not there + , + "style": { + "alignItems": "center", + "color": "black", + "display": "flex", + "flex": 1, + "flexDirection": "column", + "fontSize": 36, + "justifyContent": "center", + "lineHeight": 1.2, + "overflow": "hidden", + }, + }, + "type": "div", + }, + ], + "style": { "alignItems": "stretch", "backgroundColor": "white", "display": "flex", "flexDirection": "row", "height": "100vh", "width": "100%", - } - } -> -
- - Something is not there - -
-
+ }, + }, + "type": "div", +} `; exports[`renderResponse middleware correctly renders image wich conditional content 2`] = ` -
+ Something is there + , + "style": { + "alignItems": "center", + "color": "black", + "display": "flex", + "flex": 1, + "flexDirection": "column", + "fontSize": 36, + "justifyContent": "center", + "lineHeight": 1.2, + "overflow": "hidden", + }, + }, + "type": "div", + }, + ], + "style": { "alignItems": "stretch", "backgroundColor": "white", "display": "flex", "flexDirection": "row", "height": "100vh", "width": "100%", - } - } -> -
- - Something is there - -
-
+ }, + }, + "type": "div", +} `; exports[`renderResponse middleware properly resolves against basePath 1`] = `""`; diff --git a/packages/frames.js/src/middleware/farcaster.ts b/packages/frames.js/src/middleware/farcaster.ts index 3bf6acae5..37e6a8ec1 100644 --- a/packages/frames.js/src/middleware/farcaster.ts +++ b/packages/frames.js/src/middleware/farcaster.ts @@ -1,14 +1,13 @@ +import type { ClientProtocolId, FrameActionPayload } from "../types"; import { - ClientProtocolId, - FrameActionPayload, - FrameMessageReturnType, + type FrameMessageReturnType, getFrameMessage, -} from ".."; +} from "../getFrameMessage"; import { InvalidFrameActionPayloadError, RequestBodyNotJSONError, } from "../core/errors"; -import { FramesMiddleware, JsonValue } from "../core/types"; +import type { FramesMiddleware, JsonValue } from "../core/types"; function isValidFrameActionPayload( value: unknown diff --git a/packages/frames.js/src/middleware/farcasterHubContext.ts b/packages/frames.js/src/middleware/farcasterHubContext.ts index 8ab40feb5..fbbd7c9b3 100644 --- a/packages/frames.js/src/middleware/farcasterHubContext.ts +++ b/packages/frames.js/src/middleware/farcasterHubContext.ts @@ -1,15 +1,17 @@ -import { +import type { ClientProtocolId, FrameActionPayload, - FrameMessageReturnType, HubHttpUrlOptions, +} from "../types"; +import { + type FrameMessageReturnType, getFrameMessage, -} from ".."; +} from "../getFrameMessage"; import { InvalidFrameActionPayloadError, RequestBodyNotJSONError, } from "../core/errors"; -import { FramesMiddleware, JsonValue } from "../core/types"; +import type { FramesMiddleware, JsonValue } from "../core/types"; function isValidFrameActionPayload( value: unknown diff --git a/packages/frames.js/src/middleware/framesjsMiddleware.ts b/packages/frames.js/src/middleware/framesjsMiddleware.ts index be60a8afc..d635a9bd6 100644 --- a/packages/frames.js/src/middleware/framesjsMiddleware.ts +++ b/packages/frames.js/src/middleware/framesjsMiddleware.ts @@ -1,4 +1,4 @@ -import { FramesMiddleware } from "../core/types"; +import type { FramesMiddleware } from "../core/types"; import { isFrameRedirect, parseButtonInformationFromTargetURL, diff --git a/packages/frames.js/src/middleware/openframes.ts b/packages/frames.js/src/middleware/openframes.ts index 986fc9d3a..7805ae7ee 100644 --- a/packages/frames.js/src/middleware/openframes.ts +++ b/packages/frames.js/src/middleware/openframes.ts @@ -1,6 +1,9 @@ -import { ClientProtocolId } from ".."; +import type { ClientProtocolId } from "../types"; import { RequestBodyNotJSONError } from "../core/errors"; -import { FramesMiddleware, FramesMiddlewareReturnType } from "../core/types"; +import type { + FramesMiddleware, + FramesMiddlewareReturnType, +} from "../core/types"; import { isFrameDefinition } from "../core/utils"; type OpenFrameMessage = any; diff --git a/packages/frames.js/src/middleware/renderResponse.tsx b/packages/frames.js/src/middleware/renderResponse.ts similarity index 90% rename from packages/frames.js/src/middleware/renderResponse.tsx rename to packages/frames.js/src/middleware/renderResponse.ts index 0daccccfc..9372c5e20 100644 --- a/packages/frames.js/src/middleware/renderResponse.tsx +++ b/packages/frames.js/src/middleware/renderResponse.ts @@ -1,8 +1,9 @@ -import React from "react"; import { ImageResponse } from "@vercel/og"; -import { type Frame, getFrameFlattened, getFrameHtmlHead } from ".."; +import { getFrameHtmlHead } from "../getFrameHtml"; +import { getFrameFlattened } from "../getFrameFlattened"; +import { type Frame } from "../types"; import type { ButtonProps } from "../core/components"; -import { +import type { FrameButtonElement, FrameDefinition, FramesHandlerFunctionReturnType, @@ -249,34 +250,41 @@ async function renderImage( options: FrameDefinition["imageOptions"] ): Promise { const response = new ImageResponse( - ( -
-
- {element} -
-
- ), + }, + children: [ + { + type: "div", + key: "", + props: { + style: { + display: "flex", + flexDirection: "column", + justifyContent: "center", + alignItems: "center", + lineHeight: 1.2, + fontSize: 36, + color: "black", + flex: 1, + overflow: "hidden", + }, + children: element, + }, + }, + ], + }, + }, { ...(options?.aspectRatio === "1:1" ? { diff --git a/packages/frames.js/src/middleware/stateMiddleware.ts b/packages/frames.js/src/middleware/stateMiddleware.ts index 99ba78f8c..1da2dc5dd 100644 --- a/packages/frames.js/src/middleware/stateMiddleware.ts +++ b/packages/frames.js/src/middleware/stateMiddleware.ts @@ -1,4 +1,4 @@ -import { FramesMiddleware, JsonValue } from "../core/types"; +import type { FramesMiddleware, JsonValue } from "../core/types"; type StateMiddlewareContext = { /** diff --git a/packages/frames.js/src/next/fetchMetadata.ts b/packages/frames.js/src/next/fetchMetadata.ts index 2a7b9b6f5..8be82c3f8 100644 --- a/packages/frames.js/src/next/fetchMetadata.ts +++ b/packages/frames.js/src/next/fetchMetadata.ts @@ -1,6 +1,6 @@ -import type { FrameFlattened } from ".."; +import type { FrameFlattened } from "../types"; import { FRAMES_META_TAGS_HEADER } from "../core"; -import { Metadata } from "next"; +import type { Metadata } from "next"; /** * Fetches meta tags from your Frames app that can be used in Next.js generateMetadata() function. diff --git a/packages/frames.js/src/next/index.ts b/packages/frames.js/src/next/index.ts index 51dd555be..8d79ebc79 100644 --- a/packages/frames.js/src/next/index.ts +++ b/packages/frames.js/src/next/index.ts @@ -1,6 +1,6 @@ import { createFrames as coreCreateFrames, types } from "../core"; import type { NextRequest, NextResponse } from "next/server"; -import { CoreMiddleware } from "../middleware"; +import type { CoreMiddleware } from "../middleware"; import { getCurrentUrl } from "./getCurrentUrl"; export { Button, type types } from "../core"; diff --git a/packages/frames.js/src/next/pages-router.tsx b/packages/frames.js/src/next/pages-router.tsx index b522bc6b8..bf229f862 100644 --- a/packages/frames.js/src/next/pages-router.tsx +++ b/packages/frames.js/src/next/pages-router.tsx @@ -1,4 +1,4 @@ -import { Metadata, NextApiRequest, NextApiResponse } from "next"; +import type { Metadata, NextApiRequest, NextApiResponse } from "next"; import { createFrames as coreCreateFrames } from "../core"; import { createReadableStreamFromReadable, diff --git a/packages/frames.js/src/next/server.tsx b/packages/frames.js/src/next/server.tsx index 20ffd0dfd..2b4f945ac 100644 --- a/packages/frames.js/src/next/server.tsx +++ b/packages/frames.js/src/next/server.tsx @@ -6,20 +6,20 @@ import { } from "next/server"; import React from "react"; import { - FrameMessageReturnType, - GetFrameMessageOptions, - getByteLength, - validateFrameMessage, + type FrameMessageReturnType, + type GetFrameMessageOptions, getFrameMessage as _getFrameMessage, -} from ".."; -import { +} from "../getFrameMessage"; +import { getByteLength } from '../utils' +import { validateFrameMessage } from '../validateFrameMessage'; +import type { ActionIndex, ClientProtocolId, FrameActionPayload, HubHttpUrlOptions, ImageAspectRatio, } from "../types"; -import { +import type { Dispatch, FrameButtonAutomatedProps, FrameButtonProvidedProps, diff --git a/packages/frames.js/src/next/types.ts b/packages/frames.js/src/next/types.ts index 5fd79492d..d397e5b91 100644 --- a/packages/frames.js/src/next/types.ts +++ b/packages/frames.js/src/next/types.ts @@ -1,4 +1,4 @@ -import { ActionIndex, FrameActionPayload } from "../types"; +import type { ActionIndex, FrameActionPayload } from "../types"; /** * A subset of HTTP request headers provided to the server request diff --git a/packages/frames.js/src/remix/fetchMetadata.ts b/packages/frames.js/src/remix/fetchMetadata.ts index 65605d3be..08d5d1935 100644 --- a/packages/frames.js/src/remix/fetchMetadata.ts +++ b/packages/frames.js/src/remix/fetchMetadata.ts @@ -1,4 +1,4 @@ -import type { FrameFlattened } from ".."; +import type { FrameFlattened } from "../types"; import { FRAMES_META_TAGS_HEADER } from "../core"; import type { MetaFunction } from "@remix-run/node"; diff --git a/packages/frames.js/src/remix/index.ts b/packages/frames.js/src/remix/index.ts index 9888e030d..7a17f14a3 100644 --- a/packages/frames.js/src/remix/index.ts +++ b/packages/frames.js/src/remix/index.ts @@ -1,6 +1,6 @@ import type { ActionFunctionArgs, LoaderFunctionArgs } from "@remix-run/node"; import { createFrames as coreCreateFrames, types } from "../core"; -import { CoreMiddleware } from "../middleware"; +import type { CoreMiddleware } from "../middleware"; export { Button, type types } from "../core"; export { fetchMetadata } from "./fetchMetadata"; diff --git a/packages/frames.js/src/types.ts b/packages/frames.js/src/types.ts index 0ce5720fa..de4c10566 100644 --- a/packages/frames.js/src/types.ts +++ b/packages/frames.js/src/types.ts @@ -1,4 +1,4 @@ -import { Abi } from "viem"; +import type { Abi } from "viem"; export type FrameVersion = "vNext" | `${number}-${number}-${number}`; diff --git a/packages/frames.js/src/utils.ts b/packages/frames.js/src/utils.ts index 35138dd9b..74664a627 100644 --- a/packages/frames.js/src/utils.ts +++ b/packages/frames.js/src/utils.ts @@ -1,5 +1,5 @@ import { CastId, Message, MessageType, Protocol } from "./farcaster"; -import { +import type { FrameActionPayload, FrameButton, FrameButtonLink, diff --git a/packages/frames.js/src/validateFrameMessage.ts b/packages/frames.js/src/validateFrameMessage.ts index ab526bfe0..ec073595b 100644 --- a/packages/frames.js/src/validateFrameMessage.ts +++ b/packages/frames.js/src/validateFrameMessage.ts @@ -1,10 +1,7 @@ -import { - FrameActionPayload, - HubHttpUrlOptions, - hexStringToUint8Array, -} from "."; +import type { FrameActionPayload, HubHttpUrlOptions } from "./types"; +import { hexStringToUint8Array } from "./utils"; import { DEFAULT_HUB_API_KEY, DEFAULT_HUB_API_URL } from "./default"; -import { FrameActionMessage, Message } from "./farcaster"; +import { type FrameActionMessage, Message } from "./farcaster"; /** * @returns a Promise that resolves with whether the message signature is valid, by querying a Farcaster hub, as well as the message itself diff --git a/packages/frames.js/tsup.config.ts b/packages/frames.js/tsup.config.ts new file mode 100644 index 000000000..d8aaecbc1 --- /dev/null +++ b/packages/frames.js/tsup.config.ts @@ -0,0 +1,15 @@ +import { dirname } from "node:path"; +import { fileURLToPath } from "node:url"; +import { defineConfig } from "tsup"; +import glob from "fast-glob"; + +export default defineConfig({ + dts: true, + format: ["cjs", "esm"], + clean: true, + entry: glob.sync("src/**/*.{ts,tsx}", { + ignore: ["**/*.test.{ts,tsx}", "**/*.snap"], + onlyFiles: true, + cwd: dirname(fileURLToPath(import.meta.url)), + }), +}); diff --git a/packages/render/package.json b/packages/render/package.json index 613645fb3..923d90bd3 100644 --- a/packages/render/package.json +++ b/packages/render/package.json @@ -14,7 +14,7 @@ }, "scripts": { "lint": "eslint \"./src/**/*.{ts,tsx}\"", - "build": "NODE_OPTIONS='--max-old-space-size=16384' tsup `find ./src -type f \\( -regex '.*\\.tsx*' -a -not -regex '.*\\.test\\.tsx*' \\)` --format cjs,esm --dts", + "build": "NODE_OPTIONS='--max-old-space-size=16384' tsup", "dev": "npm run build -- --watch", "test:watch": "jest --watch" }, @@ -83,4 +83,4 @@ "@farcaster/core": "^0.14.7", "frames.js": "^0.10.0" } -} \ No newline at end of file +} diff --git a/packages/render/tsup.config.ts b/packages/render/tsup.config.ts new file mode 100644 index 000000000..d8aaecbc1 --- /dev/null +++ b/packages/render/tsup.config.ts @@ -0,0 +1,15 @@ +import { dirname } from "node:path"; +import { fileURLToPath } from "node:url"; +import { defineConfig } from "tsup"; +import glob from "fast-glob"; + +export default defineConfig({ + dts: true, + format: ["cjs", "esm"], + clean: true, + entry: glob.sync("src/**/*.{ts,tsx}", { + ignore: ["**/*.test.{ts,tsx}", "**/*.snap"], + onlyFiles: true, + cwd: dirname(fileURLToPath(import.meta.url)), + }), +}); From 65c7f6c9741308e19d22e5aff57a9201b9754e56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kvasnic=CC=8Ca=CC=81k?= Date: Wed, 27 Mar 2024 12:43:50 +0100 Subject: [PATCH 20/42] chore: changeset --- .changeset/warm-pandas-laugh.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/warm-pandas-laugh.md diff --git a/.changeset/warm-pandas-laugh.md b/.changeset/warm-pandas-laugh.md new file mode 100644 index 000000000..6a5f16ce2 --- /dev/null +++ b/.changeset/warm-pandas-laugh.md @@ -0,0 +1,5 @@ +--- +"frames.js": patch +--- + +fix: correctly tree shake the bundle From fdea64267fabae0062c00139d5bea695cc9964a1 Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Mon, 25 Mar 2024 16:45:34 +0200 Subject: [PATCH 21/42] feat: createFrames params --- docs/pages/reference/core/createFrames.mdx | 48 +++++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/docs/pages/reference/core/createFrames.mdx b/docs/pages/reference/core/createFrames.mdx index f7b4f66ad..d38f9065c 100644 --- a/docs/pages/reference/core/createFrames.mdx +++ b/docs/pages/reference/core/createFrames.mdx @@ -17,6 +17,51 @@ const handleRequest = frames(async (ctx) => { The function passed to `frames` will be called with the context of a frame action and should return a `FrameDefinition`. +## Parameters + +`createFrames` accepts an optional options object with the following properties: + +### `basePath` + +- Type: `string` + +A string that specifies the base path for all relative URLs in the frame definition. It defaults to `/`. + +### `initialState` + +- Type: generic + +A JSON serializable value that is used if no state is provided in the message or you are on the initial frame. + +### `middleware` + +Type: `FramesMiddleware` + +An array of middleware functions that are called before the frame handler and allows you to inject additional context into the `ctx` parameter passed to each frame handler call. + +Each middleware should return a promise that resolves to the next middleware, or a [Web API `Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response), or a `FrameDefinition`. + +#### Example + +```tsx [./app/frames/route.tsx] +const frames = createFrames({ + middleware: [ + async (ctx, next) => { + console.log("Before frame handler"); + const result = await next({name: "Alice"}); + console.log("After frame handler"); + return result; + }, + ], +}); + +const handler = frames(async (ctx) => { + return { + image: {ctx.name}, // Outputs an image with the text "Alice" + }; +}); +``` + ## FrameDefinition `FrameDefinition` is an object that describes a frame. It has the following properties: @@ -84,8 +129,7 @@ const handleRequest = frames(async (ctx) => { aspectRatio: "1:1", }, buttons: [], - headers: { - // [!code focus] + headers: {// [!code focus] // Max cache age in seconds // [!code focus] "Cache-Control": "max-age=0", // [!code focus] }, // [!code focus] From 82c41d83b8b597c463fa98b40e45fe8b5cff6ca5 Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Mon, 25 Mar 2024 16:50:54 +0200 Subject: [PATCH 22/42] fix: clean up example filenames, add steps --- docs/pages/guides/create-frame.mdx | 34 ++++++++++-------- docs/pages/guides/display-frames.mdx | 44 ++++++++++++----------- docs/pages/index.mdx | 23 +++++------- docs/pages/reference/core/Button.mdx | 3 +- docs/pages/reference/core/next/index.mdx | 6 ++-- docs/pages/reference/core/remix/index.mdx | 6 ++-- 6 files changed, 57 insertions(+), 59 deletions(-) diff --git a/docs/pages/guides/create-frame.mdx b/docs/pages/guides/create-frame.mdx index 0528d582d..cc6403853 100644 --- a/docs/pages/guides/create-frame.mdx +++ b/docs/pages/guides/create-frame.mdx @@ -1,5 +1,5 @@ --- -title: "Guide: Display Frames in your app" +title: "Guide: Create your first Frame" description: "Frames.js is the react based framework for making frames. Debugger included." --- @@ -8,21 +8,26 @@ description: "Frames.js is the react based framework for making frames. Debugger This guide shows you how to add frames rendering to your next.js + tailwind app using frames.js. ## Steps +::::steps +### Create a new repo -1. Create a new repo +Create a new Next.js app -`npx create-next-app@latest my-project --ts --eslint --tailwind --app` +```sh +npx create-next-app@latest my-project --ts --eslint --tailwind --app +cd my-project +``` -`cd my-project` +Add `frames.js` to your project -`yarn add frames.js` +```sh +yarn add frames.js +``` -`yarn install` -2. Create your Frames app +### Create your Frames app -```tsx filename="// ./app/frames/route.tsx" -// ./app/frames/route.tsx +```tsx [./app/frames/route.tsx] /* eslint-disable react/jsx-key */ import { createFrames, Button } from "frames.js/next"; @@ -51,10 +56,9 @@ export const GET = handleRequest; export const POST = handleRequest; ``` -3. If you have an existing page, render Frames in your metadata +### If you have an existing page, render Frames in your metadata -```tsx filename="// ./app/page.tsx" -// ./app/page.tsx +```tsx [./app/page.tsx] import { fetchMetadata } from "frames.js/next"; export async function generateMetadata() { @@ -72,6 +76,8 @@ export default function Page() { } ``` -4. Run `yarn run dev` +### Run `yarn run dev` + +### Done! 🎉 -5. Done! 🎉 +:::: diff --git a/docs/pages/guides/display-frames.mdx b/docs/pages/guides/display-frames.mdx index 6506f5617..298bd9fdd 100644 --- a/docs/pages/guides/display-frames.mdx +++ b/docs/pages/guides/display-frames.mdx @@ -9,26 +9,32 @@ This guide shows you how to add frames rendering to your next.js + tailwind app ## Steps -1. Create a new repo +::::steps -`npx create-next-app@latest my-project --ts --eslint --tailwind --app` +### Create a new repo -`cd my-project` -`yarn add @frames.js/render` +Create a new Next.js app -`yarn install` +```sh +npx create-next-app@latest my-project --ts --eslint --tailwind --app +cd my-project +``` + +Add `@frames.js/render` to your project -2. Add proxies for routing frame requests via your backend for privacy + preventing CORS issues -```tsx filename="// ./app/frames/route.tsx" -// ./app/frames/route.tsx +```sh +yarn add @frames.js/render +``` + +### Add proxies for routing frame requests via your backend for privacy + preventing CORS issues +```tsx [./app/frames/route.tsx] export { GET, POST } from "@frames.js/render/next"; ``` -3. Add the renderer to your page +### Add the renderer to your page -```tsx filename="// ./app/page.tsx" -// ./app/page.tsx +```tsx [./app/page.tsx] "use client"; import { FrameUI, @@ -81,10 +87,9 @@ export default function Page() { ``` -4. In order for the styles to work, your project should have tailwind set up as well as the tailwind.config.js rule +### In order for the styles to work, your project should have tailwind set up as well as the tailwind.config.js rule -```tsx filename="// tailwind.config.js" -// tailwind.config.js +```tsx [tailwind.config.js] const config = { // ... content: [ @@ -97,10 +102,9 @@ const config = { } ``` -5. Allow images from any domain +### Allow images from any domain -```tsx filename="// next.config.js" -// next.config.js +```tsx [next.config.js] const nextConfig = { images: { remotePatterns: [ @@ -113,10 +117,10 @@ const nextConfig = { }; ``` -6. Run `yarn run dev` - -7. Done! 🎉 +### Run `yarn run dev` +### Done! 🎉 +:::: ### Optional diff --git a/docs/pages/index.mdx b/docs/pages/index.mdx index d91135701..d4ce3b591 100644 --- a/docs/pages/index.mdx +++ b/docs/pages/index.mdx @@ -65,9 +65,7 @@ pnpm create frames yarn add frames.js ``` -```tsx filename="// ./app/page.tsx" -// ./app/page.tsx - +```tsx [./app/page.tsx] import { fetchMetadata } from "frames.js/next"; export async function generateMetadata() { @@ -89,8 +87,7 @@ export default function Home(props) { } ``` -```ts filename="./app/frames/route.tsx" -// ./app/frames/route.tsx +```ts [./app/frames/route.tsx] /* eslint-disable react/jsx-key */ import { createFrames, Button } from 'frames.js/next'; @@ -126,14 +123,12 @@ Check out the following places for more Frames-related content: Or use the [hosted Frames debugger](https://debugger.framesjs.org/?url=https%3A%2F%2Fframesjs.org). Running locally has the benefits of it working with natively with localhost. -## Prefer to not use JSX? - -### Use frames.js in Next.js using helper functions +## Prefer to not use JSX? -```tsx filename="./app/page.tsx" -// page that renders a frame -// ./app/page.tsx +### frames.js in Next.js using helper functions +```tsx [./app/page.tsx] +// Page that returns a frame import { Frame, getFrameFlattened } from "frames.js"; import type { Metadata } from "next"; @@ -164,10 +159,8 @@ export const metadata: Metadata = { }; ``` -```ts filename="app/frames/route.ts" -// handle frame actions -// ./app/frames/route.ts - +```ts [./app/frames/route.ts] +// Route that handles frame actions import { getFrameHtml, validateFrameMessage } from "frames.js"; import { NextRequest } from "next/server"; diff --git a/docs/pages/reference/core/Button.mdx b/docs/pages/reference/core/Button.mdx index 38daa078a..7fad906b4 100644 --- a/docs/pages/reference/core/Button.mdx +++ b/docs/pages/reference/core/Button.mdx @@ -114,8 +114,7 @@ type EthSendTransactionParams { If the transaction is successful, the frame will send a POST request to the URL specified in `post_url` or the frame `post_url`. This can be handled by the frame to show a success message or redirect the user to a different page. -```tsx -// /route.tsx +```tsx [route.tsx] import { Button } from "frames.js/next"; import { createFrames } from "frames.js/next"; diff --git a/docs/pages/reference/core/next/index.mdx b/docs/pages/reference/core/next/index.mdx index 12a719491..1324c6a91 100644 --- a/docs/pages/reference/core/next/index.mdx +++ b/docs/pages/reference/core/next/index.mdx @@ -8,8 +8,7 @@ Frames.js can be easily integrated with [Next.js](https://nextjs.org) applicatio Frames handler is responsible for rendering your Frames and also reacts to user interactions with buttons. -```tsx -// app/frames/route.tsx +```tsx [./app/frames/route.tsx] /* eslint-disable react/jsx-key */ import { createFrames, Button } from "frames.js/next"; @@ -29,8 +28,7 @@ export const POST = handleRequest; In order to render the initial frame of your Frames app on some of your pages, you need to render frame metadata. That can be achieved using [`generateMetadata() API`](https://nextjs.org/docs/app/api-reference/functions/generate-metadata). -```tsx -// app/page.tsx +```tsx [./app/page.tsx] import { fetchMetadata } from "frames.js/next"; export async function generateMetadata() { diff --git a/docs/pages/reference/core/remix/index.mdx b/docs/pages/reference/core/remix/index.mdx index 5649e9e0a..2282f209a 100644 --- a/docs/pages/reference/core/remix/index.mdx +++ b/docs/pages/reference/core/remix/index.mdx @@ -8,8 +8,7 @@ Frames.js can be easily integrated with [Remix](https://remix.run) applications. Frames handler is responsible for rendering your Frames and also reacts to user interactions with buttons. -```tsx -// app/routes/frames.tsx +```tsx [./app/routes/frames.tsx] /* eslint-disable react/jsx-key */ import { createFrames, Button } from "frames.js/remix"; @@ -27,8 +26,7 @@ export const loader = handleRequest; ### Render initial frame on your existing page -```tsx -// app/routes/_index.tsx +```tsx [./app/routes/_index.tsx] import { fetchMetadata } from "frames.js/remix"; export async function loader({ request }) { From 166b785443f1c7d953f42f3a330ebac8f5dc10ee Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Mon, 25 Mar 2024 17:04:13 +0200 Subject: [PATCH 23/42] fix: frames.js for apps, @frames.js/render imports in docs --- .../guides/{ => apps}/display-frames.mdx | 0 docs/pages/reference/render/frame-ui.mdx | 8 ++-- .../reference/render/next/frame-image.mdx | 8 ++-- docs/pages/reference/render/next/get.mdx | 4 +- docs/pages/reference/render/next/post.mdx | 4 +- docs/pages/reference/render/types.mdx | 6 +-- docs/pages/reference/render/use-frame.mdx | 23 ++++----- docs/vocs.config.tsx | 48 +++++++++++-------- 8 files changed, 53 insertions(+), 48 deletions(-) rename docs/pages/guides/{ => apps}/display-frames.mdx (100%) diff --git a/docs/pages/guides/display-frames.mdx b/docs/pages/guides/apps/display-frames.mdx similarity index 100% rename from docs/pages/guides/display-frames.mdx rename to docs/pages/guides/apps/display-frames.mdx diff --git a/docs/pages/reference/render/frame-ui.mdx b/docs/pages/reference/render/frame-ui.mdx index eb062c277..3611f3807 100644 --- a/docs/pages/reference/render/frame-ui.mdx +++ b/docs/pages/reference/render/frame-ui.mdx @@ -3,9 +3,9 @@ ## Usage ```tsx [frames.js/render/types.tsx] -import { FrameUI, fallbackFrameContext } from 'frames.js/render'; -import { FrameImageNext } from "frames.js/render/next"; -import { useFrame } from "frames.js/render/use-frame"; +import { FrameUI, fallbackFrameContext } from "@frames.js/render'; +import { FrameImageNext } from "@frames.js/render/next"; +import { useFrame } from "@frames.js/render/use-frame"; export const Page(){ @@ -35,4 +35,4 @@ const config = { "./node_modules/frames.js/dist/render/*.{ts,tsx,js,css}", "./node_modules/frames.js/dist/**/*.{ts,tsx,js,css}", ] -``` \ No newline at end of file +``` diff --git a/docs/pages/reference/render/next/frame-image.mdx b/docs/pages/reference/render/next/frame-image.mdx index 10141f77e..278daa50f 100644 --- a/docs/pages/reference/render/next/frame-image.mdx +++ b/docs/pages/reference/render/next/frame-image.mdx @@ -3,9 +3,9 @@ ## Usage ```tsx [frames.js/render/types.tsx] -import { FrameUI, fallbackFrameContext } from 'frames.js/render'; -import { useFrame } from 'frames.js/render/use-frame'; -import { FrameImageNext } from "frames.js/render/next"; +import { FrameUI, fallbackFrameContext } from "@frames.js/render'; +import { useFrame } from "@frames.js/render/use-frame'; +import { FrameImageNext } from "@frames.js/render/next"; export const Page(){ // ... @@ -18,4 +18,4 @@ export const Page(){ ); } -``` \ No newline at end of file +``` diff --git a/docs/pages/reference/render/next/get.mdx b/docs/pages/reference/render/next/get.mdx index bbf8b888d..b6dabd9fd 100644 --- a/docs/pages/reference/render/next/get.mdx +++ b/docs/pages/reference/render/next/get.mdx @@ -3,5 +3,5 @@ ## Usage ```tsx [./frames/route.tsx] -export { GET, POST } from 'frames.js/render/next'; -``` \ No newline at end of file +export { GET, POST } from "@frames.js/render/next'; +``` diff --git a/docs/pages/reference/render/next/post.mdx b/docs/pages/reference/render/next/post.mdx index 9c36324b2..d372a38fb 100644 --- a/docs/pages/reference/render/next/post.mdx +++ b/docs/pages/reference/render/next/post.mdx @@ -3,5 +3,5 @@ ## Usage ```tsx [./frames/route.tsx] -export { GET, POST } from 'frames.js/render/next'; -``` \ No newline at end of file +export { GET, POST } from "@frames.js/render/next'; +``` diff --git a/docs/pages/reference/render/types.mdx b/docs/pages/reference/render/types.mdx index bcb838fe1..14b3668f3 100644 --- a/docs/pages/reference/render/types.mdx +++ b/docs/pages/reference/render/types.mdx @@ -3,7 +3,7 @@ ## Example usage ```tsx -import { SignerStateInstance } from "frames.js/render"; +import { SignerStateInstance } from "@frames.js/render"; ``` ## Reference @@ -142,6 +142,4 @@ export type FrameTheme = Partial>; export interface FrameActionBodyPayload {} export type FrameContext = FarcasterFrameContext; - - -``` \ No newline at end of file +``` diff --git a/docs/pages/reference/render/use-frame.mdx b/docs/pages/reference/render/use-frame.mdx index 1e37aaee4..299b47d86 100644 --- a/docs/pages/reference/render/use-frame.mdx +++ b/docs/pages/reference/render/use-frame.mdx @@ -18,22 +18,21 @@ type Props = { onMint?: (t: onMintArgs) => void; /** the context of this frame, used for generating Frame Action payloads */ frameContext: FrameContext; -} +}; ``` ## Usage ```tsx [frames.js/render/types.tsx] "use client"; -import { - FrameUI, - fallbackFrameContext, - FrameContext, -} from "frames.js/render"; -import { FrameImageNext } from "frames.js/render/next"; +import { FrameUI, fallbackFrameContext, FrameContext } from "@frames.js/render"; +import { FrameImageNext } from "@frames.js/render/next"; import { FrameButton } from "frames.js"; -import { useFrame } from "frames.js/render/use-frame"; -import { mockFarcasterSigner, createFrameActionMessageWithSignerKey } from "frames.js/render/farcaster"; +import { useFrame } from "@frames.js/render/use-frame"; +import { + mockFarcasterSigner, + createFrameActionMessageWithSignerKey, +} from "@frames.js/render/farcaster"; export default function Page() { const frameState = useFrame({ @@ -54,7 +53,9 @@ export default function Page() { // Implement me alert("A frame button was pressed without a signer."); }, - signFrameAction: () => { alert('implement me.') }, + signFrameAction: () => { + alert("implement me."); + }, }, }); @@ -64,4 +65,4 @@ export default function Page() { } ``` -[Full example](/guides/display-frames.mdx) \ No newline at end of file +[Full example](/guides/apps/display-frames.mdx) diff --git a/docs/vocs.config.tsx b/docs/vocs.config.tsx index 000647e80..da3cf2784 100644 --- a/docs/vocs.config.tsx +++ b/docs/vocs.config.tsx @@ -50,16 +50,22 @@ const sidebar = [ text: "Transactions", link: "/guides/transactions", }, - { - text: "Display Frames", - link: "/guides/display-frames", - }, { text: "Open Frames", link: "/guides/open-frames", }, ], }, + { + text: "Frames.js for Apps", + collapsed: false, + items: [ + { + text: "Display Frames", + link: "/guides/apps/display-frames", + }, + ], + }, { text: "Write your frame with", collapsed: false, @@ -232,7 +238,7 @@ const sidebar = [ ], }, { - text: "frames.js/render", + text: "@frames.js/render", collapsed: true, items: [ { @@ -247,23 +253,23 @@ const sidebar = [ text: "FrameUI", link: "/reference/render/frame-ui", }, - ], - }, - { - text: "frames.js/render/next", - collapsed: true, - items: [ - { - text: "FrameImage", - link: "/reference/render/next/frame-image", - }, { - text: "POST", - link: "/reference/render/next/POST", - }, - { - text: "GET", - link: "/reference/render/next/GET", + text: "Next.js", + collapsed: true, + items: [ + { + text: "FrameImage", + link: "/reference/render/next/frame-image", + }, + { + text: "POST", + link: "/reference/render/next/POST", + }, + { + text: "GET", + link: "/reference/render/next/GET", + }, + ], }, ], }, From e0753e9f10acbf407754d676a88e3776f33ff168 Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Mon, 25 Mar 2024 17:29:09 +0200 Subject: [PATCH 24/42] feat: context reference --- .changeset/new-emus-love.md | 8 +++ docs/pages/reference/core/createFrames.mdx | 68 ++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 .changeset/new-emus-love.md diff --git a/.changeset/new-emus-love.md b/.changeset/new-emus-love.md new file mode 100644 index 000000000..e0434dd52 --- /dev/null +++ b/.changeset/new-emus-love.md @@ -0,0 +1,8 @@ +--- +"docs": patch +--- + +- Adds default context reference to `createFrames` reference +- "Frames.js for apps" section +- Clean up example filenames, add steps +- `createFrames` params diff --git a/docs/pages/reference/core/createFrames.mdx b/docs/pages/reference/core/createFrames.mdx index d38f9065c..32a9870d2 100644 --- a/docs/pages/reference/core/createFrames.mdx +++ b/docs/pages/reference/core/createFrames.mdx @@ -146,3 +146,71 @@ handleRequest(new Request("/")).then((res) => { return res.text(); }); ``` + +## Context + +Core middleware is included and executed by default and gives you access to the following default context in your frame handlers: + +### `basePath` + +- Type: `string` + +Specifies the base path for all relative URLs in the frame definition. + +### `initialState` + +- Type: generic + +A JSON serializable value that is used if no state is provided in the message or you are on the initial frame. + +### `request` + +- Type: [Web API `Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) + +The request object that was passed to the request handler. + +### `url` + +- Type: [Web API `URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) + +The URL object that was parsed from the request. + +### `searchParams` + +- Type: `Record` + +The search params in the URL as an object. If there are no search params, it will be an empty object. + +### `pressedButton` + +- Type: `undefined | { action: "post" | "post_redirect"; index: 1 | 2 | 3 | 4 }` + +The button that was clicked on the previous frame. + +### `buttonIndex` + +- Type: `number` + +The index of the button that was clicked on the previous frame. + +### `message` + +- Type: `FrameMessage` + +The frame message that was parsed from the request body. + +### `clientProtocol` + +- Type: `ClientProtocolId` + +The client protocol that was used to send the frame message. + +### `state` + +- Type: `JsonValue` + +The state extracted from the frame message. If you are on the initial frame (no button pressed), the value is the `initialState` value passed to `createFrames`. If you are on a frame with a button pressed, the value is the state from the previous frame. + + + + From d65714fb36d8295ef616c4e83fb215e9280ce43b Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Mon, 25 Mar 2024 21:54:40 +0200 Subject: [PATCH 25/42] feat: add note about per-route middleware --- docs/pages/reference/core/createFrames.mdx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/pages/reference/core/createFrames.mdx b/docs/pages/reference/core/createFrames.mdx index 32a9870d2..6b30573d9 100644 --- a/docs/pages/reference/core/createFrames.mdx +++ b/docs/pages/reference/core/createFrames.mdx @@ -147,6 +147,24 @@ handleRequest(new Request("/")).then((res) => { }); ``` +### Per-route middleware + +You can also pass middleware to the `handleRequest` function to be executed only for that specific route. + +```tsx +const handleRequest = frames(async (ctx) => { + return { + image: Test, + }; +}, { + middleware: [ + farcasterHubContext({ hubHttpUrl: process.env.HUB_HTTP_URL }), + ] +}); +``` + +This will only execute the `farcasterHubContext` middleware for the route that `handleRequest` is called with. + ## Context Core middleware is included and executed by default and gives you access to the following default context in your frame handlers: From 856428a507956d14477ffd84cf0d6a44cd9ca57c Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Tue, 26 Mar 2024 15:51:18 +0200 Subject: [PATCH 26/42] feat: troubleshooting --- docs/pages/troubleshooting.mdx | 139 +++++++++++++++++++++++++++++++++ docs/vocs.config.tsx | 4 + 2 files changed, 143 insertions(+) create mode 100644 docs/pages/troubleshooting.mdx diff --git a/docs/pages/troubleshooting.mdx b/docs/pages/troubleshooting.mdx new file mode 100644 index 000000000..bb6479f4d --- /dev/null +++ b/docs/pages/troubleshooting.mdx @@ -0,0 +1,139 @@ +# Troubleshooting + +## Image not rendering + +### Image too large + +If the image is not rendering, it may be too large. + +- If you are including a full size external `` element, consider passing the external image as a string instead: + +```tsx +return { + image: "https://example.com/image.jpg", +}; +``` + +- Try resizing it to a smaller size via the `imageOptions` of the returned `FrameDefinition`. + +```tsx +return { + image:
...
, + imageOptions: { + width: 100, + height: 100, + }, +}; +``` + +### Image wrong format + +If the image is not rendering, it may be in the wrong format. SVG images are typically not supported on mobile. + +## Initial frame not loading + +Ensure that the `fetchMetadata` URL is correct and that it is inside the `other` folder for Next.js. + +### `VERCEL_URL` environment variable + +If you are using Vercel, the `VERCEL_URL` environment variable is not a fully qualified URL and may cause issues with `fetchMetadata`. You will have to prepend the protocol `VERCEL_URL`. + +```tsx +export async function generateMetadata() { + const frameMetadata = await fetchMetadata( + new URL( + "/frames", + process.env.VERCEL_URL + ? `https://${process.env.VERCEL_URL}` + : "http://localhost:3000" + ) + ); + + return { + title: "My page", + other: { + ...frameMetadata, + }, + }; +} +``` + +### Vercel authentication + +When deploying to Vercel, your site will not automatically be accessible to the public. You will need to disable Vercel Authentication under `Settings > Deployment Protection > Vercel Authentication` + +## Import type errors + +If you are getting type errors when importing `frames.js`, you may need to change the `moduleResolution` in your `tsconfig.json` from `node` to `nodenext`. + +```json +{ + "compilerOptions": { + "moduleResolution": "nodenext" + } +} +``` + +## Unable to access frame message on initial frame + +The initial frame is accessed via a GET request and does not have access to frame message and hence user data. + +## Type error: Route ... does not match the required types of a Next.js Route + +If you are getting this error you are exporting something other than a Next.js route from a `route.tsx` or `page.tsx` file. + +We recommend creating a new file for your `frames` app and importing it in the routes that use it. + +### Example + +Frames app file + +```tsx [frames.ts] +import { createFrames } from "frames.js/next"; + +export const frames = createFrames({ + basePath: "/frames", +}); +``` + +Initial page route + +```tsx [route.tsx] +import { frames } from "./frames"; + +export const GET = frames(async (ctx) => { + // ctx.message is not available in the initial frame + return { + image:
...
, + buttons: [ + , + ], + }; +}); +``` + +Frame action handler route + +```tsx [my-route/route.tsx] +import { frames } from "../frames"; + +export const POST = frames(async (ctx) => { + // Do something with ctx.message + // ... + + return { + image:
...
, + buttons: [ + // ... + ], + }; +}); +``` + +## Combining old and new SDKs + +You cannot use the ``, `` and `` components from the old SDK (`frames.js/next/server`) with the new SDK (`frames.js/next`). + +The new SDK uses a [`FrameDefinition`](/reference/core/createFrames#framedefinition) object to define a frame. diff --git a/docs/vocs.config.tsx b/docs/vocs.config.tsx index da3cf2784..e3eccd0ec 100644 --- a/docs/vocs.config.tsx +++ b/docs/vocs.config.tsx @@ -102,6 +102,10 @@ const sidebar = [ }, ], }, + { + text: "Troubleshooting", + link: "/troubleshooting", + }, { text: "Reference", // link: "/reference", From b2e96c0051fde191f04d92c0d1d2569498f46da4 Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Tue, 26 Mar 2024 15:51:50 +0200 Subject: [PATCH 27/42] fix: FrameDefinition types --- docs/pages/reference/core/createFrames.mdx | 83 +++++++++++++--------- 1 file changed, 49 insertions(+), 34 deletions(-) diff --git a/docs/pages/reference/core/createFrames.mdx b/docs/pages/reference/core/createFrames.mdx index 6b30573d9..c30ea287d 100644 --- a/docs/pages/reference/core/createFrames.mdx +++ b/docs/pages/reference/core/createFrames.mdx @@ -66,43 +66,58 @@ const handler = frames(async (ctx) => { `FrameDefinition` is an object that describes a frame. It has the following properties: +### `image` + +- Type: `React.ReactElement | string` + +The image to be rendered in the frame. If a string is provided, it must be a valid URL. + +### `imageOptions` + +- Type: `{ aspectRatio?: "1.91:1" | "1:1" } & ConstructorParameters[1]` + +Options for the image. The `aspectRatio` property can be set to `"1.91:1"` or `"1:1"`. + +### `buttons` + +- Type: 1, 2, 3, or 4 `FrameButtonElement` elements + +An array of buttons to be rendered in the frame. The buttons are rendered in the order they are provided. + +#### Example + ```tsx -/** - * Frame definition, this is rendered by the frames - */ -export type FrameDefinition = { - /** - * If string then it must be a valid URL - */ - image: React.ReactElement | string; - imageOptions?: { - /** - * @default '1.91:1' - */ - aspectRatio?: "1.91:1" | "1:1"; - } & ConstructorParameters[1]; - buttons?: - | [] - | [FrameButtonElement] - | [FrameButtonElement, FrameButtonElement] - | [FrameButtonElement, FrameButtonElement, FrameButtonElement] - | [ - FrameButtonElement, - FrameButtonElement, - FrameButtonElement, - FrameButtonElement, - ]; - /** - * Label for text input, if no value is provided the input is not rendered - */ - textInput?: string; - /** - * Global app state that will be available on next frame - */ - state?: JsonValue; -} & ResponseInit; +import { Button } from "frames.js/next"; + +const handleRequest = frames(async (ctx) => { + return { + image: Test, + buttons: [ + , + , + ], + }; +}); ``` +### `textInput` + +- Type: `string` + +Label for text input. If no value is provided, the input is not rendered. + +### `state` + +- Type: `JsonValue` + +Global app state that will be available on the next frame. + +### `headers` + +- Type: `HeadersInit` + +Custom headers to be included in the response. + The `ResponseInit` properties allow you to specify custom headers such as `Cache-Control`. ### Cache-Control From e9acd3a7fbcefd3c43b8e57aee12c118cd93f860 Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Tue, 26 Mar 2024 16:08:10 +0200 Subject: [PATCH 28/42] fix: troubleshooting file name --- docs/pages/troubleshooting.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/troubleshooting.mdx b/docs/pages/troubleshooting.mdx index bb6479f4d..53333f68a 100644 --- a/docs/pages/troubleshooting.mdx +++ b/docs/pages/troubleshooting.mdx @@ -66,7 +66,7 @@ When deploying to Vercel, your site will not automatically be accessible to the If you are getting type errors when importing `frames.js`, you may need to change the `moduleResolution` in your `tsconfig.json` from `node` to `nodenext`. -```json +```json [tsconfig.json] { "compilerOptions": { "moduleResolution": "nodenext" From fa4e870b2b607d04af55faa9286be67ae5ab9e94 Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Tue, 26 Mar 2024 17:24:15 +0200 Subject: [PATCH 29/42] feat: middleware docs, minor improvements --- docs/pages/guides/create-frame.mdx | 11 +- docs/pages/guides/middleware.mdx | 134 +++++++++++++++------ docs/pages/reference/core/Button.mdx | 2 +- docs/pages/reference/core/createFrames.mdx | 42 ++++--- docs/pages/troubleshooting.mdx | 2 +- 5 files changed, 139 insertions(+), 52 deletions(-) diff --git a/docs/pages/guides/create-frame.mdx b/docs/pages/guides/create-frame.mdx index cc6403853..f6e9fbae4 100644 --- a/docs/pages/guides/create-frame.mdx +++ b/docs/pages/guides/create-frame.mdx @@ -27,11 +27,18 @@ yarn add frames.js ### Create your Frames app +```tsx [./app/frames/frames.ts] +import { createFrames } from "frames.js/next"; + +export const frames = createFrames(); +``` + +### Create a route ```tsx [./app/frames/route.tsx] /* eslint-disable react/jsx-key */ -import { createFrames, Button } from "frames.js/next"; +import { Button } from "frames.js/next"; +import { frames } from "./frames"; -const frames = createFrames(); const handleRequest = frames(async (ctx) => { return { image: ( diff --git a/docs/pages/guides/middleware.mdx b/docs/pages/guides/middleware.mdx index d3e0de689..11f253e50 100644 --- a/docs/pages/guides/middleware.mdx +++ b/docs/pages/guides/middleware.mdx @@ -7,47 +7,113 @@ description: "" Frames.js uses middleware to extend the functionality of Frames, bringing in data from API providers, verifying frame actions and adding Open Frames support. -You can use middleware for all your frames by passing in middleware via the `middleware` Option. +You can use middleware for all your frames by passing in middleware via the `middleware` option in `createFrames` or you can specify per-route middleware. -```tsx -import { farcasterHubContext, openframes } from "frames.js/middleware"; -import { createFrames } from "frames.js/next"; -import { getXmtpFrameMessage, isXmtpFrameActionPayload } from "frames.js/xmtp"; +## Using middleware -const DEFAULT_DEBUGGER_URL = - process.env.DEBUGGER_URL ?? "http://localhost:3010/"; +Include the middleware in your `createFrames` call: -export const DEFAULT_DEBUGGER_HUB_URL = - process.env.NODE_ENV === "development" - ? new URL("/hub", DEFAULT_DEBUGGER_URL).toString() - : undefined; +```tsx [frames.ts] +import { farcasterHubContext } from "frames.js/middleware"; +import { createFrames } from "frames.js/next"; const frames = createFrames({ basePath: "/", initialState: { pageIndex: 0, }, - middleware: [ - farcasterHubContext({ - hubHttpUrl: DEFAULT_DEBUGGER_HUB_URL, - }), - openframes({ - clientProtocol: { - id: "xmtp", - version: "2024-02-09", - }, - handler: { - isValidPayload: (body: JSON) => isXmtpFrameActionPayload(body), - getFrameMessage: async (body: JSON) => { - if (!isXmtpFrameActionPayload(body)) { - return undefined; - } - const result = await getXmtpFrameMessage(body); - - return { ...result }; - }, - }, - }), - ], + middleware: [farcasterHubContext()], +}); +``` + +```tsx [frames/username/route.tsx] +import { frames } from "./frames"; + +export const POST = frames(async (ctx) => { + // The added context from the middleware will be available on `ctx` here + if (!ctx.message.isValid) { + throw new Error("Invalid message"); + } + + return { + image: ( +
The user's username is {ctx.message.requesterUserData.username}
+ ), + }; +}); +``` + +### Per-route middleware + +You can also specify middleware per-route that will only be applied to that route: + +```tsx [frames/username/route.tsx] +import { farcasterHubContext } from "frames.js/middleware"; + +export const POST = frames( + async (ctx) => { + // The added context from the middleware will be available on `ctx` here + if (!ctx.message.isValid) { + throw new Error("Invalid message"); + } + + return { + image: ( +
+ The user's username is {ctx.message.requesterUserData.username} +
+ ), + }; + }, + { + middleware: [farcasterHubContext()], + } +); +``` + +## Defining your own middleware + +You can define your own middleware by creating a function that returns a promise that resolves to the next middleware, or a [Web API `Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response), or a `FrameDefinition`. + +Middleware can modify the context or return a response that will terminate the request early. + +### Adding context + +:::code-group + +```tsx [frames.ts] +import { createFrames, types } from "frames.js/next"; + +const myMiddleware: types.FramesMiddleware< + any, + { foo: string } +> = async (ctx, next) => { + return next({ foo: "bar" }); +}; + +export const frames = createFrames({ + basePath: "/", + initialState: { + pageIndex: 0, + }, + // Add the middleware + middleware: [myMiddleware], }); -``` \ No newline at end of file +``` + +```tsx [frames/route.tsx] +import { Button } from "frames.js/next"; +import { frames } from "./frames"; + +const handler = frames(async (ctx) => { + return { + // Use the additional contect + image:
foo: ${ctx.bar}
, + }; +}); + +export const GET = handler; +export const POST = handler; +``` + +::: diff --git a/docs/pages/reference/core/Button.mdx b/docs/pages/reference/core/Button.mdx index 7fad906b4..919aefccf 100644 --- a/docs/pages/reference/core/Button.mdx +++ b/docs/pages/reference/core/Button.mdx @@ -123,7 +123,7 @@ const export frames = createFrames() export const GET = frames(async (ctx) => { return { image: ( -
+
Execute transaction
), diff --git a/docs/pages/reference/core/createFrames.mdx b/docs/pages/reference/core/createFrames.mdx index c30ea287d..9cbdde563 100644 --- a/docs/pages/reference/core/createFrames.mdx +++ b/docs/pages/reference/core/createFrames.mdx @@ -35,12 +35,29 @@ A JSON serializable value that is used if no state is provided in the message or ### `middleware` +See the [Middleware guide](/guides/middleware) for more information. + Type: `FramesMiddleware` An array of middleware functions that are called before the frame handler and allows you to inject additional context into the `ctx` parameter passed to each frame handler call. Each middleware should return a promise that resolves to the next middleware, or a [Web API `Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response), or a `FrameDefinition`. +#### Types + +For strong type support in the handler, the middleware should be typed as `FramesMiddleware`. + +```tsx +import { createFrames, types } from "frames.js/next"; + +const myMiddleware: types.FramesMiddleware< + any, + { foo?: string } +> = async (ctx, next) => { + return next({ foo: "bar" }); +}; +``` + #### Example ```tsx [./app/frames/route.tsx] @@ -48,7 +65,7 @@ const frames = createFrames({ middleware: [ async (ctx, next) => { console.log("Before frame handler"); - const result = await next({name: "Alice"}); + const result = await next({ name: "Alice" }); console.log("After frame handler"); return result; }, @@ -167,15 +184,16 @@ handleRequest(new Request("/")).then((res) => { You can also pass middleware to the `handleRequest` function to be executed only for that specific route. ```tsx -const handleRequest = frames(async (ctx) => { - return { - image: Test, - }; -}, { - middleware: [ - farcasterHubContext({ hubHttpUrl: process.env.HUB_HTTP_URL }), - ] -}); +const handleRequest = frames( + async (ctx) => { + return { + image: Test, + }; + }, + { + middleware: [farcasterHubContext({ hubHttpUrl: process.env.HUB_HTTP_URL })], + } +); ``` This will only execute the `farcasterHubContext` middleware for the route that `handleRequest` is called with. @@ -243,7 +261,3 @@ The client protocol that was used to send the frame message. - Type: `JsonValue` The state extracted from the frame message. If you are on the initial frame (no button pressed), the value is the `initialState` value passed to `createFrames`. If you are on a frame with a button pressed, the value is the state from the previous frame. - - - - diff --git a/docs/pages/troubleshooting.mdx b/docs/pages/troubleshooting.mdx index 53333f68a..27ad5ca51 100644 --- a/docs/pages/troubleshooting.mdx +++ b/docs/pages/troubleshooting.mdx @@ -60,7 +60,7 @@ export async function generateMetadata() { ### Vercel authentication -When deploying to Vercel, your site will not automatically be accessible to the public. You will need to disable Vercel Authentication under `Settings > Deployment Protection > Vercel Authentication` +When deploying to Vercel, your site will not automatically be accessible to the public. You will need to disable Vercel Authentication under your project's `Settings > Deployment Protection > Vercel Authentication` on vercel.com. ## Import type errors From 1a68dc5014acb9f01d4113ce4a53bbadcd89d2c7 Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Tue, 26 Mar 2024 17:44:08 +0200 Subject: [PATCH 30/42] fix: update use-frame docs --- docs/pages/reference/render/use-frame.mdx | 153 +++++++++++++++++++--- 1 file changed, 135 insertions(+), 18 deletions(-) diff --git a/docs/pages/reference/render/use-frame.mdx b/docs/pages/reference/render/use-frame.mdx index 299b47d86..dc0115491 100644 --- a/docs/pages/reference/render/use-frame.mdx +++ b/docs/pages/reference/render/use-frame.mdx @@ -2,24 +2,141 @@ ## Props -```ts -type Props = { - /** the route used to POST frame actions. The post_url will be added as a the `url` query parameter */ - frameActionProxy: string; - /** the route used to GET the initial frame via proxy */ - frameGetProxy: string; - /** an auth state object used to determine what actions are possible */ - signerState: SignerStateInstance; - /** the url of the homeframe, if null won't load a frame */ - homeframeUrl: string | null; - /** the initial frame. if not specified will fetch it from the url prop */ - frame?: Frame; - /** a function to handle mint buttons */ - onMint?: (t: onMintArgs) => void; - /** the context of this frame, used for generating Frame Action payloads */ - frameContext: FrameContext; -}; -``` +### `dangerousSkipSigning` + +- Type: `boolean` + +If true, the frame will not be signed before being sent to the frameActionProxy. This is useful for frames that don't verify signatures. + +### `frameActionProxy` + +- Type: `string` + +The route used to POST frame actions. The post_url will be added as a the `url` query parameter. + +### `frameGetProxy` + +- Type: `string` + +The route used to GET the initial frame via proxy. + +### `signerState` + +- Type: `SignerStateInstance` + +An signer state object used to determine what actions are possible. + +### `homeframeUrl` + +- Type: `string | null` + +The url of the homeframe, if null won't load a frame. + +### `frame` + +- Type: `Frame` + +The initial frame. if not specified will fetch it from the url prop. + +### `onMint` + +- Type: `(t: onMintArgs) => void` + +A function to handle mint buttons. + +### `onTransaction` + +- Type: `OnTransactionFunc` + +A function to handle transaction button presses, returns the transaction hash or null. + +### `frameContext` + +- Type: `FrameContext` + +The context of this frame, used for generating Frame Action payloads. + +### `extraButtonRequestPayload` + +- Type: `Record` + +Extra data appended to the frame action payload. + +## Returns + +- Type: `FrameState` + +### `fetchFrame` + +- Type: `(request: FrameRequest) => void` + +Fetches a frame from the frameGetProxy. + +### `clearFrameStack` + +- Type: `() => void` + +Clears the frame stack. + +### `frame` + +- Type: `Frame | null` + +The frame at the top of the stack (at index 0). + +### `framesStack` + +- Type: `FramesStack` + +A stack of frames with additional context, with the most recent frame at index 0. + +### `isLoading` + +- Type: `null | FrameStackPending` + +Whether the frame is loading. + +### `inputText` + +- Type: `string` + +The input text. + +### `setInputText` + +- Type: `(s: string) => void` + +Sets the input text. + +### `onButtonPress` + +- Type: `(frameButton: FrameButton, index: number) => void` + +Handles a button press. + +### `isFrameValid` + +- Type: `boolean | undefined` + +Whether the frame at the top of the stack has any frame validation errors. Undefined when the frame is not loaded or set. + +### `frameValidationErrors` + +- Type: `Record | undefined | null` + +The frame validation errors. + +### `error` + +- Type: `null | unknown` + +Whether there was an error loading the frame. + +### `homeframeUrl` + +- Type: `string | null` + +The url of the frame. ## Usage From 22ad5850e072a7567a555a2795a3f6fb0d66f6d9 Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Wed, 27 Mar 2024 10:31:31 +0200 Subject: [PATCH 31/42] chore: move old apis to a deprecated apis section --- docs/vocs.config.tsx | 117 ++++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 56 deletions(-) diff --git a/docs/vocs.config.tsx b/docs/vocs.config.tsx index e3eccd0ec..f79d9b67f 100644 --- a/docs/vocs.config.tsx +++ b/docs/vocs.config.tsx @@ -185,62 +185,6 @@ const sidebar = [ }, ], }, - { - text: "frames.js/next/server", - collapsed: true, - items: [ - { - text: "getPreviousFrame", - link: "/reference/nextjs/getPreviousFrame", - }, - { - text: "POST", - link: "/reference/nextjs/POST", - }, - ], - }, - { - text: "frames.js/next/server - [react]", - collapsed: true, - items: [ - { - text: "types", - link: "/reference/react/types", - }, - { - text: "FrameContainer", - link: "/reference/react/FrameContainer", - }, - { - text: "FrameButton", - link: "/reference/react/FrameButton", - }, - { - text: "FrameImage", - link: "/reference/react/FrameImage", - }, - { - text: "FrameInput", - link: "/reference/react/FrameInput", - }, - { - text: "parseFrameParams", - link: "/reference/react/parseFrameParams", - }, - { - text: "useFramesReducer", - link: "/reference/react/useFramesReducer", - }, - { - text: "validateActionSignature", - link: "/reference/react/validateActionSignature", - }, - { - text: "createPreviousFrame", - link: "/reference/react/createPreviousFrame", - }, - ], - }, { text: "@frames.js/render", collapsed: true, @@ -277,6 +221,67 @@ const sidebar = [ }, ], }, + { + text: "Deprecated APIs", + items: [ + { + text: "frames.js/next/server", + collapsed: true, + items: [ + { + text: "getPreviousFrame", + link: "/reference/nextjs/getPreviousFrame", + }, + { + text: "POST", + link: "/reference/nextjs/POST", + }, + ], + }, + { + text: "frames.js/next/server - [react]", + collapsed: true, + items: [ + { + text: "types", + link: "/reference/react/types", + }, + { + text: "FrameContainer", + link: "/reference/react/FrameContainer", + }, + { + text: "FrameButton", + link: "/reference/react/FrameButton", + }, + { + text: "FrameImage", + link: "/reference/react/FrameImage", + }, + { + text: "FrameInput", + link: "/reference/react/FrameInput", + }, + { + text: "parseFrameParams", + link: "/reference/react/parseFrameParams", + }, + { + text: "useFramesReducer", + link: "/reference/react/useFramesReducer", + }, + { + text: "validateActionSignature", + link: "/reference/react/validateActionSignature", + }, + { + text: "createPreviousFrame", + link: "/reference/react/createPreviousFrame", + }, + ], + }, + ], + }, ], }, ]; From db8e61257f951570af3c6c7a999a1cf65d0e65f1 Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Wed, 27 Mar 2024 10:33:31 +0200 Subject: [PATCH 32/42] fix: make button docs more visible, multi-page docs --- docs/pages/guides/create-frame.mdx | 19 ++- docs/pages/guides/multiple-frames.mdx | 185 ++++++++++++++++++++------ docs/pages/reference/core/Button.mdx | 18 ++- 3 files changed, 172 insertions(+), 50 deletions(-) diff --git a/docs/pages/guides/create-frame.mdx b/docs/pages/guides/create-frame.mdx index f6e9fbae4..3e29ef334 100644 --- a/docs/pages/guides/create-frame.mdx +++ b/docs/pages/guides/create-frame.mdx @@ -8,7 +8,9 @@ description: "Frames.js is the react based framework for making frames. Debugger This guide shows you how to add frames rendering to your next.js + tailwind app using frames.js. ## Steps + ::::steps + ### Create a new repo Create a new Next.js app @@ -24,7 +26,6 @@ Add `frames.js` to your project yarn add frames.js ``` - ### Create your Frames app ```tsx [./app/frames/frames.ts] @@ -34,6 +35,7 @@ export const frames = createFrames(); ``` ### Create a route + ```tsx [./app/frames/route.tsx] /* eslint-disable react/jsx-key */ import { Button } from "frames.js/next"; @@ -49,10 +51,10 @@ const handleRequest = frames(async (ctx) => { ), buttons: [ - , - , ], @@ -73,7 +75,12 @@ export async function generateMetadata() { title: "My Page", // provide a full URL to your /frames endpoint other: await fetchMetadata( - new URL("/frames", process.env.VERCEL_URL ? `https://${process.env.VERCEL_URL}` : "http://localhost:3000") + new URL( + "/frames", + process.env.VERCEL_URL + ? `https://${process.env.VERCEL_URL}` + : "http://localhost:3000" + ) ), }; } @@ -88,3 +95,7 @@ export default function Page() { ### Done! 🎉 :::: + +## Next Steps + +- Read the [`createFrames`](/reference/core/createFrames) and [`Button`](/reference/core/Button) documentation diff --git a/docs/pages/guides/multiple-frames.mdx b/docs/pages/guides/multiple-frames.mdx index 2cff40e25..37e30b68f 100644 --- a/docs/pages/guides/multiple-frames.mdx +++ b/docs/pages/guides/multiple-frames.mdx @@ -5,67 +5,168 @@ description: "" # Multi-Page Frames -You will want to connect multiple frames together. -There's two different ways of navigating between frames. +Frames.js can be used to create multi-page applications by defining multiple Frames that are linked together. -The first way is by defining the `state` prop of a `Button`, and using that state to return a different Frame in the handler. See below +## Creating a Multi-Page Application -```tsx -/* eslint-disable react/jsx-key */ -import { createFrames, Button } from "frames.js/next"; +Frames are connected by [`Button`](/reference/core/Button) targets, similar to how Next.js `Link` components work. + +:::steps + +### Create your frames app + +We create a new directory `./frames` with a `frames.ts` file to export our frames application from because it needs to be used from multiple routes. -const totalPages = 5; +```tsx [frames.ts] +import { createFrames } from "frames.js/next"; -const frames = createFrames({ - basePath: "/examples/new-api/frames", - initialState: { - pageIndex: 0, - }, +export const frames = createFrames({ + basePath: "/frames", }); +``` + +### Define your initial route -const handleRequest = frames(async (ctx) => { - const pageIndex = Number(ctx.searchParams.pageIndex || 0); +The first frame is always fetched via a GET request and is typically included alongside existing OpenGraph data via the [`generateMetadata`](https://nextjs.org/docs/app/api-reference/functions/generate-metadata) function in Next.js if you have an existing site. - const imageUrl = `https://picsum.photos/seed/frames.js-${pageIndex}/300/200`; +#### Define the initial frame +Create a `./frames/route.tsx` file that contains your initial frame. This frame will include buttons to navigate to other frames. + +```tsx [route.tsx] +/* eslint-disable react/jsx-key */ +import { frames } from "./frames"; +import { Button } from "frames.js/next"; + +export const GET = frames(async () => { return { - image: ( -
- Image -
- This is slide {pageIndex + 1} / {totalPages} -
-
- ), + image:
Welcome
, buttons: [ + // With query params , - , ], - textInput: "Type something!", }; }); +``` + +#### Export the initial frame metadata + +In your `page.tsx` file, fetch the initial frame's metadata and include it alongside your existing page's metadata. -export const GET = handleRequest; -export const POST = handleRequest; +`fetchMetadata` is a helper function that fetches the metadata for a frame from the frames.js handler and formats it for use in the `generateMetadata` function. + +```tsx [page.tsx] +import { fetchMetadata } from "frames.js/next"; + +export async function generateMetadata() { + return { + title: "My Page", + // provide a full URL to your /frames endpoint + other: await fetchMetadata( + new URL( + "/frames", + process.env.VERCEL_URL + ? `https://${process.env.VERCEL_URL}` + : "http://localhost:3000" + ) + ), + }; +} + +export default function Page() { + return My existing page; +} ``` -The second way to navigate between frames is by defining a `Button` with `type`, `post`, with a `target` that points at another Frame. -This can be a Frame on the same domain, or a Frame on another website entirely. In order to link between Frames in the same project, you need to set up a frames.js handler on the `POST` route of the path defined in the target. +### Create the other routes + +Create additional frames in the `./frames` directory. + +#### Route 1 + +Create a directory `./frames/route1/route.tsx` with a `POST` handler that returns the frame content. + +```tsx [route1.tsx] +/* eslint-disable react/jsx-key */ +import { frames } from "../frames"; +import { Button } from "frames.js/next"; + +export const POST = frames(async (ctx) => { + const foo = ctx.searchParams.foo; + + return { + image:
Route 1 foo: {foo}
, // foo: bar + buttons: [ + , + ], + }; +}); +``` + +#### Route 2 + +Create a directory `./frames/route2/route.tsx` with a `POST` handler that returns the frame content. + +```tsx [route2.tsx] +/* eslint-disable react/jsx-key */ +import { frames } from "../frames"; +import { Button } from "frames.js/next"; + +export const POST = frames(async () => { + return { + image:
Route 2
, + buttons: [ + , + ], + }; +}); +``` + +### (Optional) Navigate back to the initial frame -{/* -TODO: Link to examples - */} \ No newline at end of file +If you want to navigate back to the initial frame you need to export a `POST` handler for the initial route. You may want to refactor the initial frame handler into a `frameHandler` variable that is exported as both `GET` and `POST` + +```tsx [route.tsx] +import { frames } from "./frames"; + +const frameHandler = frames(async () => { + return { + image:
Welcome
+ buttons: [ + , + , + ], + }; +}); + +export const GET = frameHandler; +export const POST = frameHandler; +``` + +You can then navigate back to the initial frame by linking to the initial route. + +```tsx + +``` + +::: + +## Notes + +The second way to navigate between frames is by defining a [`Button`](/reference/core/Button) with `type`, `post`, with a `target` that points at another Frame. +This can be a Frame on the same domain, or a Frame on another website entirely. In order to link between Frames in the same project, you need to set up a frames.js handler on the `POST` route of the path defined in the target. diff --git a/docs/pages/reference/core/Button.mdx b/docs/pages/reference/core/Button.mdx index 919aefccf..e95a4d30b 100644 --- a/docs/pages/reference/core/Button.mdx +++ b/docs/pages/reference/core/Button.mdx @@ -20,15 +20,22 @@ This button sends a request to a URL on which it was rendered. If you want to na The `target` path will be resolved relatively to current URL. -### Passing state when button is clicked using query parameters +### Passing state between frames ```tsx - ``` -The state will be available in handler `ctx.pressedButton.state`. +The state will be available in the frame handler via `ctx.searchParams` e.g. + +```ts +ctx.searchParams.foo; // bar +``` ## Post Redirect Button @@ -39,7 +46,10 @@ It accepts same props as `post` button. ```tsx import { Button } from "frames.js/core"; -; ``` From 45c1c99ea941dc2afd4f0708ffd918939ec706af Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Wed, 27 Mar 2024 11:54:30 +0200 Subject: [PATCH 33/42] feat: accessing request body via middleware --- docs/pages/guides/middleware.mdx | 42 +++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/docs/pages/guides/middleware.mdx b/docs/pages/guides/middleware.mdx index 11f253e50..aa0d761e2 100644 --- a/docs/pages/guides/middleware.mdx +++ b/docs/pages/guides/middleware.mdx @@ -37,7 +37,9 @@ export const POST = frames(async (ctx) => { return { image: ( -
The user's username is {ctx.message.requesterUserData.username}
+
+ The user's username is {ctx.message.requesterUserData.username} +
), }; }); @@ -73,7 +75,7 @@ export const POST = frames( ## Defining your own middleware -You can define your own middleware by creating a function that returns a promise that resolves to the next middleware, or a [Web API `Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response), or a `FrameDefinition`. +You can define your own middleware by creating a function that returns a promise that resolves to the next middleware, or a [Web API `Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response), or a [`FrameDefinition`](/reference/core/createFrames#framedefinition). Middleware can modify the context or return a response that will terminate the request early. @@ -84,10 +86,10 @@ Middleware can modify the context or return a response that will terminate the r ```tsx [frames.ts] import { createFrames, types } from "frames.js/next"; -const myMiddleware: types.FramesMiddleware< - any, - { foo: string } -> = async (ctx, next) => { +const myMiddleware: types.FramesMiddleware = async ( + ctx, + next +) => { return next({ foo: "bar" }); }; @@ -117,3 +119,31 @@ export const POST = handler; ``` ::: + + +### Accessing the request object + +Sometimes you want to access the request object in your middleware - whenever you do this, you should clone the request object to avoid mutating it and breaking other middleware. + +Here's an example of creating middleware which will add the request json to your context: + +```tsx +import { createFrames, types } from "frames.js/next"; + +const bodyMiddleware: types.FramesMiddleware = async ( + ctx, + next +) => { + const body = await ctx.request.clone().json(); + return next({ body }); +}; + +export const frames = createFrames({ + basePath: "/", + initialState: { + pageIndex: 0, + }, + middleware: [bodyMiddleware], + // The request body will now be available via `ctx.body` in your frame handlers +}); +``` From 9497b7e85230661e4192e5a8993ece7cceff72bc Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Wed, 27 Mar 2024 14:05:11 +0200 Subject: [PATCH 34/42] chore: update changeset --- .changeset/new-emus-love.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.changeset/new-emus-love.md b/.changeset/new-emus-love.md index e0434dd52..8386bcdd2 100644 --- a/.changeset/new-emus-love.md +++ b/.changeset/new-emus-love.md @@ -2,7 +2,11 @@ "docs": patch --- -- Adds default context reference to `createFrames` reference -- "Frames.js for apps" section -- Clean up example filenames, add steps -- `createFrames` params +- adds default context reference to createFrames reference +- frames.js for apps section +- clean up example filenames, add steps +- createFrames params +- troubleshooting docs +- update useFrame reference +- make button docs more visible +- multi-page guide From 0b681fb958cead18312b7e867d6c90c14daba155 Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Wed, 27 Mar 2024 15:23:33 +0200 Subject: [PATCH 35/42] fix: expose new types and utils --- .changeset/sweet-rivers-join.md | 5 +++++ .../frames/frames.ts | 13 ++++++----- packages/frames.js/package.json | 22 ++++++++++++++++++- 3 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 .changeset/sweet-rivers-join.md diff --git a/.changeset/sweet-rivers-join.md b/.changeset/sweet-rivers-join.md new file mode 100644 index 000000000..e2e5b11db --- /dev/null +++ b/.changeset/sweet-rivers-join.md @@ -0,0 +1,5 @@ +--- +"frames.js": patch +--- + +fix: expose core types and utils via frames.js/types and frames.js/utils diff --git a/examples/framesjs-starter/app/examples/new-api-custom-middleware/frames/frames.ts b/examples/framesjs-starter/app/examples/new-api-custom-middleware/frames/frames.ts index eee185c92..b37090590 100644 --- a/examples/framesjs-starter/app/examples/new-api-custom-middleware/frames/frames.ts +++ b/examples/framesjs-starter/app/examples/new-api-custom-middleware/frames/frames.ts @@ -1,9 +1,12 @@ -import { createFrames, types } from "frames.js/next"; +import { createFrames } from "frames.js/next"; +import { FramesMiddleware } from "frames.js/types"; -const priceMiddleware: types.FramesMiddleware< - any, - { ethPrice?: number } -> = async (ctx, next) => { +type PriceContext = { ethPrice?: number }; + +const priceMiddleware: FramesMiddleware = async ( + ctx, + next +) => { try { const res = await fetch( "https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd" diff --git a/packages/frames.js/package.json b/packages/frames.js/package.json index 36864a2c6..f986a9a39 100644 --- a/packages/frames.js/package.json +++ b/packages/frames.js/package.json @@ -144,6 +144,26 @@ "default": "./dist/core/index.cjs" } }, + "./types": { + "import": { + "types": "./dist/core/types.d.ts", + "default": "./dist/core/types.js" + }, + "require": { + "types": "./dist/core/types.d.cts", + "default": "./dist/core/types.cjs" + } + }, + "./utils": { + "import": { + "types": "./dist/core/utils.d.ts", + "default": "./dist/core/utils.js" + }, + "require": { + "types": "./dist/core/utils.d.cts", + "default": "./dist/core/utils.cjs" + } + }, "./middleware": { "import": { "types": "./dist/middleware/index.d.ts", @@ -236,4 +256,4 @@ "protobufjs": "^7.2.6", "viem": "^2.7.8" } -} +} \ No newline at end of file From ceadc1ff402d306670faee10b5cb55951bce783e Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Wed, 27 Mar 2024 15:39:47 +0200 Subject: [PATCH 36/42] Update docs/pages/troubleshooting.mdx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michal Kvasničák --- docs/pages/troubleshooting.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/troubleshooting.mdx b/docs/pages/troubleshooting.mdx index 27ad5ca51..b78247153 100644 --- a/docs/pages/troubleshooting.mdx +++ b/docs/pages/troubleshooting.mdx @@ -32,7 +32,7 @@ If the image is not rendering, it may be in the wrong format. SVG images are typ ## Initial frame not loading -Ensure that the `fetchMetadata` URL is correct and that it is inside the `other` folder for Next.js. +Ensure that the `fetchMetadata` URL is correct and that it is inside the `other` property for Next.js. ### `VERCEL_URL` environment variable From 26de29b0ad9de70198e563d0492cdb502a2d3706 Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Wed, 27 Mar 2024 15:40:25 +0200 Subject: [PATCH 37/42] Update docs/pages/troubleshooting.mdx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michal Kvasničák --- docs/pages/troubleshooting.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/troubleshooting.mdx b/docs/pages/troubleshooting.mdx index b78247153..89d1d05bc 100644 --- a/docs/pages/troubleshooting.mdx +++ b/docs/pages/troubleshooting.mdx @@ -36,7 +36,7 @@ Ensure that the `fetchMetadata` URL is correct and that it is inside the `other` ### `VERCEL_URL` environment variable -If you are using Vercel, the `VERCEL_URL` environment variable is not a fully qualified URL and may cause issues with `fetchMetadata`. You will have to prepend the protocol `VERCEL_URL`. +If you are using Vercel, the `VERCEL_URL` environment variable is not a fully qualified URL and may cause issues with `fetchMetadata`. You will have to prepend the protocol to `VERCEL_URL`. ```tsx export async function generateMetadata() { From e2d5c17c9903d30a3b9fc9df045ab839d0f53b7d Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Wed, 27 Mar 2024 15:51:06 +0200 Subject: [PATCH 38/42] Update docs/pages/reference/core/createFrames.mdx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michal Kvasničák --- docs/pages/reference/core/createFrames.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/reference/core/createFrames.mdx b/docs/pages/reference/core/createFrames.mdx index 9cbdde563..9a8fbba3f 100644 --- a/docs/pages/reference/core/createFrames.mdx +++ b/docs/pages/reference/core/createFrames.mdx @@ -246,7 +246,7 @@ The index of the button that was clicked on the previous frame. ### `message` -- Type: `FrameMessage` +- Type: `FrameMessage | undefined` The frame message that was parsed from the request body. From fdc917aa252f680c9ee45f55d1c22611e21413b6 Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Wed, 27 Mar 2024 15:51:12 +0200 Subject: [PATCH 39/42] Update docs/pages/reference/core/createFrames.mdx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michal Kvasničák --- docs/pages/reference/core/createFrames.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/reference/core/createFrames.mdx b/docs/pages/reference/core/createFrames.mdx index 9a8fbba3f..be7865df2 100644 --- a/docs/pages/reference/core/createFrames.mdx +++ b/docs/pages/reference/core/createFrames.mdx @@ -252,7 +252,7 @@ The frame message that was parsed from the request body. ### `clientProtocol` -- Type: `ClientProtocolId` +- Type: `ClientProtocolId | undefined` The client protocol that was used to send the frame message. From 63b6c6b0e59aa95696dd5c3c74761ae451eb5304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kvasni=C4=8D=C3=A1k?= Date: Wed, 27 Mar 2024 14:53:18 +0100 Subject: [PATCH 40/42] docs: add cloudflare adapter docs and guide (#254) --- .changeset/heavy-nails-love.md | 6 + docs/pages/guides/deployment.mdx | 4 +- docs/pages/index.mdx | 6 - .../core/cloudflare-workers/index.mdx | 186 ++++++++++++++++++ docs/vocs.config.tsx | 4 + packages/frames.js/package.json | 10 + .../src/cloudflare-workers/index.test.tsx | 27 +++ .../frames.js/src/cloudflare-workers/index.ts | 56 ++++++ packages/frames.js/tsup.config.ts | 3 + 9 files changed, 294 insertions(+), 8 deletions(-) create mode 100644 .changeset/heavy-nails-love.md create mode 100644 docs/pages/reference/core/cloudflare-workers/index.mdx create mode 100644 packages/frames.js/src/cloudflare-workers/index.test.tsx create mode 100644 packages/frames.js/src/cloudflare-workers/index.ts diff --git a/.changeset/heavy-nails-love.md b/.changeset/heavy-nails-love.md new file mode 100644 index 000000000..66bf422a2 --- /dev/null +++ b/.changeset/heavy-nails-love.md @@ -0,0 +1,6 @@ +--- +"frames.js": minor +"docs": minor +--- + +feat: cloudflare workers adapter diff --git a/docs/pages/guides/deployment.mdx b/docs/pages/guides/deployment.mdx index 43bf95a0f..4af8358cd 100644 --- a/docs/pages/guides/deployment.mdx +++ b/docs/pages/guides/deployment.mdx @@ -7,7 +7,7 @@ description: "A guide on shipping your frames.js frame to production" Frames.js works in most javascript frameworks or libraries, and should work out of the box with whereever you would normally deploy those. -We suggest deploying your frames to Vercel, but Docker, AWS or other platforms are compatible. +We suggest deploying your frames to Vercel, but [Cloudflare Workers](/reference/core/cloudflare-workers), Docker, AWS or other platforms are compatible. ## Ensure you set up the correct `env` variables @@ -15,4 +15,4 @@ For the starter, `NEXT_PUBLIC_HOST` should be the full url (including https://) ## Vercel Deployments -Run the `vercel` command-line tool from your frame's folder to deploy your frame to vercel. \ No newline at end of file +Run the `vercel` command-line tool from your frame's folder to deploy your frame to vercel. diff --git a/docs/pages/index.mdx b/docs/pages/index.mdx index d91135701..9238310c6 100644 --- a/docs/pages/index.mdx +++ b/docs/pages/index.mdx @@ -18,12 +18,6 @@ import { HomePage } from "vocs/components"; GitHub - - Quickstart - - - GitHub - diff --git a/docs/pages/reference/core/cloudflare-workers/index.mdx b/docs/pages/reference/core/cloudflare-workers/index.mdx new file mode 100644 index 000000000..3cec8f14f --- /dev/null +++ b/docs/pages/reference/core/cloudflare-workers/index.mdx @@ -0,0 +1,186 @@ +# Cloudflare Workers integration + +Frames.js can be easily deployed to [Cloudflare Workers](https://workers.cloudflare.com). + +## Create a new project using `wrangler` + +:::code-group + +```bash [npm] +npm create cloudflare -- my-cf-frames --type hello-world --ts && cd ./my-cf-frames +``` + +```bash [yarn] +yarn create cloudflare my-cf-frames --type hello-world --ts && cd ./my-cf-frames +``` + +```bash [pnpm] +pnpm create cloudflare my-cf-frames --type hello-world --ts && cd ./my-cf-frames +``` + +::: + +## Install `frames.js` + +In order for `frames.js` to work properly in [Cloudflare Workers](https://workers.cloudflare.com) you must replace the `@vercel/og` dependency with `workers-og`. Follow following steps to override the dependency. + +::::steps + +### Override `@vercel/og` package with `workers-og` + +Add following to your `package.json`. + +:::code-group + +```json [npm] +{ + "overrides": { + "frames.js": { + "@vercel/og": "npm:workers-og@^0.0.23" + } + } +} +``` + +```json [yarn] +{ + "resolutions": { + "@vercel/og": "npm:workers-og" + } +} +``` + +```json [pnpm] +{ + "pnpm": { + "overrides": { + "@vercel/og": "npm:workers-og@^0.0.23" + } + } +} +``` + +::: + +### Install the dependencies + +After you have overridden the `@vercel/og` package with `workers-og`, you can install the dependencies. + +:::code-group + +```bash [npm] +npm install frames.js +``` + +```bash [yarn] +yarn add frames.js +``` + +```bash [pnpm] +pnpm add frames.js +``` + +::: +:::: + +## Write your Frames handler + +Open the `src/index.ts` file and replace its content with the following code. + +```tsx +import { createFrames, Button } from "frames.js/cloudflare-workers"; + +const frames = createFrames(); +const handleRequest = frames(async (ctx) => { + const hasClicked = !!(ctx.message && ctx.searchParams.clicked); + + return { + image: Clicked: {hasClicked ? "Yes" : "No"}, + buttons: hasClicked + ? [ + , + ] + : [ + , + ], + }; +}); + +export default { + fetch: handleRequest, +}; +``` + +## Develop and test locally + +You can test your Cloudflare Worker locally using `wrangler dev` and our [debugger](/guides/debugger#local-debugger-cli). Follow these steps to start developing locally: + +::::steps + +#### Start the local server + +:::code-group + +```bash [npm] +npm run dev +``` + +```bash [yarn] +yarn dev +``` + +```bash [pnpm] +pnpm dev +``` + +::: + +#### Start the debugger + +After you started the local server, you can start the debugger by running the following command where you replace `` with a URL on which local server is running (see the output of above command, e.g. `http://localhost:8787`). + +:::code-group + +```bash [npm] +npx @frames.js/debugger --url +``` + +```bash [yarn] +# yarn v1 doesn't have an alternative to npx, so you have to install the debugger globally (or use npx) +yarn global add @frames.js/debugger && frames --url + +# yarn v2 +yarn dlx @frames.js/debugger --url +``` + +```bash [pnpm] +pnpm dlx @frames.js/debugger --url +``` + +::: + +:::: + +## Deploy to Cloudflare Workers + +When you tested your Frames app locally and you are ready to deploy it to Cloudflare Workers, run the following command. + +:::code-group + +```bash [npm] +npm run deploy +``` + +```bash [yarn] +yarn deploy +``` + +```bash [pnpm] +pnpm deploy +``` + +::: diff --git a/docs/vocs.config.tsx b/docs/vocs.config.tsx index 000647e80..ee3842baf 100644 --- a/docs/vocs.config.tsx +++ b/docs/vocs.config.tsx @@ -80,6 +80,10 @@ const sidebar = [ text: "Remix", link: "/reference/core/remix", }, + { + text: 'Cloudflare Workers', + link: '/reference/core/cloudflare-workers' + } ], }, { diff --git a/packages/frames.js/package.json b/packages/frames.js/package.json index 36864a2c6..bff424d13 100644 --- a/packages/frames.js/package.json +++ b/packages/frames.js/package.json @@ -203,6 +203,16 @@ "types": "./dist/express/index.d.cts", "default": "./dist/express/index.cjs" } + }, + "./cloudflare-workers": { + "import": { + "types": "./dist/cloudflare-workers/index.d.ts", + "default": "./dist/cloudflare-workers/index.js" + }, + "require": { + "types": "./dist/cloudflare-workers/index.d.cts", + "default": "./dist/cloudflare-workers/index.cjs" + } } }, "files": [ diff --git a/packages/frames.js/src/cloudflare-workers/index.test.tsx b/packages/frames.js/src/cloudflare-workers/index.test.tsx new file mode 100644 index 000000000..932208f1c --- /dev/null +++ b/packages/frames.js/src/cloudflare-workers/index.test.tsx @@ -0,0 +1,27 @@ +import * as lib from "."; + +describe("cloudflare workers adapter", () => { + it.each(["createFrames", "Button"])("exports %s", (exportName) => { + expect(lib).toHaveProperty(exportName); + }); + + it("correctly integrates with Cloudflare Workers", async () => { + const frames = lib.createFrames(); + const handler = frames(async (ctx) => { + expect(ctx.request.url).toBe("http://localhost:3000/"); + + return { + image: Test, + buttons: [Click me], + }; + }); + + const request = new Request("http://localhost:3000"); + + // @ts-expect-error - expects fetcher property on request but it is not used by our lib + const response = await handler(request, {}, {}); + + expect(response.status).toBe(200); + expect(response.headers.get("content-type")).toBe("text/html"); + }); +}); diff --git a/packages/frames.js/src/cloudflare-workers/index.ts b/packages/frames.js/src/cloudflare-workers/index.ts new file mode 100644 index 000000000..9514d61a5 --- /dev/null +++ b/packages/frames.js/src/cloudflare-workers/index.ts @@ -0,0 +1,56 @@ +export { Button, type types } from "../core"; +import { createFrames as coreCreateFrames, types } from "../core"; +import { CoreMiddleware } from "../middleware"; +import { Buffer } from "node:buffer"; + +// make Buffer available on globalThis so it is compatible with cloudflare workers +// eslint-disable-next-line no-undef +globalThis.Buffer = Buffer; + +type CreateFramesForCloudflareWorkers = types.CreateFramesFunctionDefinition< + CoreMiddleware, + (req: Request) => Promise +>; + +/** + * Creates Frames instance to use with you Hono server + * + * @example + * import { createFrames, Button } from 'frames.js/cloudflare-workers'; + * + * const frames = createFrames(); + * const fetch = frames(async (ctx) => { + * return { + * image: Test, + * buttons: [ + * , + * ], + * }; + * }); + * + * export default { + * fetch, + * } satisfies ExportedHandler; + */ +// @ts-expect-error +export const createFrames: CreateFramesForCloudflareWorkers = + function createFramesForCloudflareWorkers( + options?: types.FramesOptions + ) { + const frames = coreCreateFrames(options); + + return function cloudflareWorkersFramesHandler< + TPerRouteMiddleware extends types.FramesMiddleware[], + >( + handler: types.FrameHandlerFunction, + handlerOptions?: types.FramesRequestHandlerFunctionOptions + ) { + const framesHandler = frames(handler, handlerOptions); + + return async function handleCloudflareWorkersRequest(req) { + return framesHandler(req); + }; + }; + }; diff --git a/packages/frames.js/tsup.config.ts b/packages/frames.js/tsup.config.ts index d8aaecbc1..43dd85baa 100644 --- a/packages/frames.js/tsup.config.ts +++ b/packages/frames.js/tsup.config.ts @@ -4,6 +4,9 @@ import { defineConfig } from "tsup"; import glob from "fast-glob"; export default defineConfig({ + // this is necessary for cloudfare workers adapter to be able to import + // buffer from cloudflare compatiblity layer + external: ["node:buffer"], dts: true, format: ["cjs", "esm"], clean: true, From 2d0131f6f2ff7ce8e085eef271f082e45488b9dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kvasni=C4=8D=C3=A1k?= Date: Wed, 27 Mar 2024 15:48:16 +0100 Subject: [PATCH 41/42] docs: fix cloudflare workers guide (#257) --- .changeset/silly-files-cheat.md | 5 ++ .../core/cloudflare-workers/index.mdx | 55 +++++++++++++++---- 2 files changed, 48 insertions(+), 12 deletions(-) create mode 100644 .changeset/silly-files-cheat.md diff --git a/.changeset/silly-files-cheat.md b/.changeset/silly-files-cheat.md new file mode 100644 index 000000000..f46e9db5a --- /dev/null +++ b/.changeset/silly-files-cheat.md @@ -0,0 +1,5 @@ +--- +"docs": patch +--- + +fix: add missing parts to cf workers guide diff --git a/docs/pages/reference/core/cloudflare-workers/index.mdx b/docs/pages/reference/core/cloudflare-workers/index.mdx index 3cec8f14f..6bda2347e 100644 --- a/docs/pages/reference/core/cloudflare-workers/index.mdx +++ b/docs/pages/reference/core/cloudflare-workers/index.mdx @@ -69,15 +69,15 @@ After you have overridden the `@vercel/og` package with `workers-og`, you can in :::code-group ```bash [npm] -npm install frames.js +npm install frames.js react ``` ```bash [yarn] -yarn add frames.js +yarn add frames.js react ``` ```bash [pnpm] -pnpm add frames.js +pnpm add frames.js react ``` ::: @@ -85,21 +85,30 @@ pnpm add frames.js ## Write your Frames handler -Open the `src/index.ts` file and replace its content with the following code. +::::steps + +### Delete generated file + +Delete the `src/index.ts` file that was generated by `wrangler`. + +### Create a file with your Frames app handler + +Create `src/index.tsx` file and paste the following code inside. -```tsx +```tsx [src/index.tsx] import { createFrames, Button } from "frames.js/cloudflare-workers"; const frames = createFrames(); -const handleRequest = frames(async (ctx) => { - const hasClicked = !!(ctx.message && ctx.searchParams.clicked); + +const fetch = frames(async ({ message, searchParams }) => { + const hasClicked = !!(message && searchParams.clicked); return { - image: Clicked: {hasClicked ? "Yes" : "No"}, - buttons: hasClicked + image: {hasClicked ? `Clicked ✅` : `Clicked ❌`},a + buttons: !hasClicked ? [ , ] : [ @@ -111,10 +120,32 @@ const handleRequest = frames(async (ctx) => { }); export default { - fetch: handleRequest, -}; + fetch, +} satisfies ExportedHandler; ``` +### Configure Typescript to use React jsx runtime + +Open `tsconfig.json` and change the value of `compilerOptions.tsx` to `react-jsx`. + +```json [tsconfig.json] +{ + "compilerOptions": { + "jsx": "react-jsx" + } +} +``` + +### Change the entrypoint for your Frames handler + +Open `wrangler.toml` and change the value of `main` to `src/index.tsx`. + +```toml [wrangler.toml] +main = "src/index.tsx" +``` + +:::: + ## Develop and test locally You can test your Cloudflare Worker locally using `wrangler dev` and our [debugger](/guides/debugger#local-debugger-cli). Follow these steps to start developing locally: From c3d1d949c5c69337657e2c9d09b8118dd6f59cd3 Mon Sep 17 00:00:00 2001 From: Stephan Cilliers <5469870+stephancill@users.noreply.github.com> Date: Wed, 27 Mar 2024 16:49:04 +0200 Subject: [PATCH 42/42] fix: changesets --- .changeset/heavy-nails-love.md | 2 +- .changeset/smooth-bugs-admire.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/heavy-nails-love.md b/.changeset/heavy-nails-love.md index 66bf422a2..6bc33beb5 100644 --- a/.changeset/heavy-nails-love.md +++ b/.changeset/heavy-nails-love.md @@ -1,6 +1,6 @@ --- "frames.js": minor -"docs": minor +"docs": patch --- feat: cloudflare workers adapter diff --git a/.changeset/smooth-bugs-admire.md b/.changeset/smooth-bugs-admire.md index a26c2a427..6fcbba274 100644 --- a/.changeset/smooth-bugs-admire.md +++ b/.changeset/smooth-bugs-admire.md @@ -1,5 +1,5 @@ --- -"create-frames": minor +"create-frames": patch --- feat: introduce cli tool to bootstrap projects from templates