From 3a98fd6d0fc54b32916bbf82cb2cc1153e73c24d Mon Sep 17 00:00:00 2001 From: Daniel Rochetti Date: Mon, 30 Oct 2023 09:01:15 -0700 Subject: [PATCH] feat: next proxy app router support (#22) * feat: add nextjs app router support * chore: rename nextjs page router demo * feat: support nextjs app router with example * chore(proxy): bump to 0.4.0 * chore: update package-lock.json * chore: remove formidable * chore: update package-lock.json * fix: page export * fix: type issues * fix: remove comment * fix: eslint any warning * chore: client version bump 0.4.2 --- .gitignore | 2 +- apps/demo-nextjs-app-router/.eslintrc.json | 40 + .../app/api/fal/proxy/route.ts | 3 + .../app/global.css} | 0 apps/demo-nextjs-app-router/app/layout.tsx | 18 + .../app/page.module.css} | 0 apps/demo-nextjs-app-router/app/page.tsx | 170 + .../index.d.ts | 0 .../jest.config.ts | 4 +- .../next-env.d.ts | 0 apps/demo-nextjs-app-router/next.config.js | 22 + .../postcss.config.js | 0 apps/demo-nextjs-app-router/project.json | 68 + .../public/.gitkeep | 0 .../demo-nextjs-app-router/public/favicon.ico | Bin 0 -> 15086 bytes .../demo-nextjs-app-router/tailwind.config.js | 18 + apps/demo-nextjs-app-router/tsconfig.json | 36 + .../demo-nextjs-app-router/tsconfig.spec.json | 21 + .../.eslintrc.json | 0 apps/demo-nextjs-page-router/index.d.ts | 6 + apps/demo-nextjs-page-router/jest.config.ts | 11 + apps/demo-nextjs-page-router/next-env.d.ts | 5 + .../next.config.js | 0 .../pages/_app.tsx | 0 .../pages/api/_fal/proxy.ts | 0 .../pages/index.module.css | 2 + .../pages/index.tsx | 18 +- apps/demo-nextjs-page-router/pages/styles.css | 400 + .../demo-nextjs-page-router/postcss.config.js | 15 + .../project.json | 22 +- apps/demo-nextjs-page-router/public/.gitkeep | 0 .../public/placeholder@2x.jpg | Bin .../specs/index.spec.tsx | 0 .../tailwind.config.js | 0 .../tsconfig.json | 0 .../tsconfig.spec.json | 0 libs/client/package.json | 2 +- libs/client/src/function.ts | 7 +- libs/proxy/package.json | 2 +- libs/proxy/src/express.ts | 2 +- libs/proxy/src/index.ts | 61 +- libs/proxy/src/nextjs.ts | 48 +- libs/proxy/tsconfig.lib.json | 1 + nx.json | 2 +- package-lock.json | 36652 +++------------- package.json | 10 +- 46 files changed, 6070 insertions(+), 31598 deletions(-) create mode 100644 apps/demo-nextjs-app-router/.eslintrc.json create mode 100644 apps/demo-nextjs-app-router/app/api/fal/proxy/route.ts rename apps/{demo-nextjs-app/pages/styles.css => demo-nextjs-app-router/app/global.css} (100%) create mode 100644 apps/demo-nextjs-app-router/app/layout.tsx rename apps/{demo-nextjs-app/pages/index.module.css => demo-nextjs-app-router/app/page.module.css} (100%) create mode 100644 apps/demo-nextjs-app-router/app/page.tsx rename apps/{demo-nextjs-app => demo-nextjs-app-router}/index.d.ts (100%) rename apps/{demo-nextjs-app => demo-nextjs-app-router}/jest.config.ts (72%) rename apps/{demo-nextjs-app => demo-nextjs-app-router}/next-env.d.ts (100%) create mode 100644 apps/demo-nextjs-app-router/next.config.js rename apps/{demo-nextjs-app => demo-nextjs-app-router}/postcss.config.js (100%) create mode 100644 apps/demo-nextjs-app-router/project.json rename apps/{demo-nextjs-app => demo-nextjs-app-router}/public/.gitkeep (100%) create mode 100644 apps/demo-nextjs-app-router/public/favicon.ico create mode 100644 apps/demo-nextjs-app-router/tailwind.config.js create mode 100644 apps/demo-nextjs-app-router/tsconfig.json create mode 100644 apps/demo-nextjs-app-router/tsconfig.spec.json rename apps/{demo-nextjs-app => demo-nextjs-page-router}/.eslintrc.json (100%) create mode 100644 apps/demo-nextjs-page-router/index.d.ts create mode 100644 apps/demo-nextjs-page-router/jest.config.ts create mode 100644 apps/demo-nextjs-page-router/next-env.d.ts rename apps/{demo-nextjs-app => demo-nextjs-page-router}/next.config.js (100%) rename apps/{demo-nextjs-app => demo-nextjs-page-router}/pages/_app.tsx (100%) rename apps/{demo-nextjs-app => demo-nextjs-page-router}/pages/api/_fal/proxy.ts (100%) create mode 100644 apps/demo-nextjs-page-router/pages/index.module.css rename apps/{demo-nextjs-app => demo-nextjs-page-router}/pages/index.tsx (94%) create mode 100644 apps/demo-nextjs-page-router/pages/styles.css create mode 100644 apps/demo-nextjs-page-router/postcss.config.js rename apps/{demo-nextjs-app => demo-nextjs-page-router}/project.json (63%) create mode 100644 apps/demo-nextjs-page-router/public/.gitkeep rename apps/{demo-nextjs-app => demo-nextjs-page-router}/public/placeholder@2x.jpg (100%) rename apps/{demo-nextjs-app => demo-nextjs-page-router}/specs/index.spec.tsx (100%) rename apps/{demo-nextjs-app => demo-nextjs-page-router}/tailwind.config.js (100%) rename apps/{demo-nextjs-app => demo-nextjs-page-router}/tsconfig.json (100%) rename apps/{demo-nextjs-app => demo-nextjs-page-router}/tsconfig.spec.json (100%) diff --git a/.gitignore b/.gitignore index 944c89d..b22eeb6 100644 --- a/.gitignore +++ b/.gitignore @@ -40,4 +40,4 @@ Thumbs.db # Next.js .next -*.local +*.local \ No newline at end of file diff --git a/apps/demo-nextjs-app-router/.eslintrc.json b/apps/demo-nextjs-app-router/.eslintrc.json new file mode 100644 index 0000000..17b0bc9 --- /dev/null +++ b/apps/demo-nextjs-app-router/.eslintrc.json @@ -0,0 +1,40 @@ +{ + "extends": [ + "plugin:@nx/react-typescript", + "next", + "next/core-web-vitals", + "../../.eslintrc.json" + ], + "ignorePatterns": ["!**/*", ".next/**/*"], + "overrides": [ + { + "files": ["*.*"], + "rules": { + "@next/next/no-html-link-for-pages": "off" + } + }, + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": { + "@next/next/no-html-link-for-pages": [ + "error", + "apps/demo-nextjs-app-router/pages" + ] + } + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.spec.ts", "*.spec.tsx", "*.spec.js", "*.spec.jsx"], + "env": { + "jest": true + } + } + ] +} diff --git a/apps/demo-nextjs-app-router/app/api/fal/proxy/route.ts b/apps/demo-nextjs-app-router/app/api/fal/proxy/route.ts new file mode 100644 index 0000000..998ab54 --- /dev/null +++ b/apps/demo-nextjs-app-router/app/api/fal/proxy/route.ts @@ -0,0 +1,3 @@ +import { route } from '@fal-ai/serverless-proxy/nextjs'; + +export const { GET, POST } = route; diff --git a/apps/demo-nextjs-app/pages/styles.css b/apps/demo-nextjs-app-router/app/global.css similarity index 100% rename from apps/demo-nextjs-app/pages/styles.css rename to apps/demo-nextjs-app-router/app/global.css diff --git a/apps/demo-nextjs-app-router/app/layout.tsx b/apps/demo-nextjs-app-router/app/layout.tsx new file mode 100644 index 0000000..836b8f4 --- /dev/null +++ b/apps/demo-nextjs-app-router/app/layout.tsx @@ -0,0 +1,18 @@ +import './global.css'; + +export const metadata = { + title: 'Welcome to demo-nextjs-app-router', + description: 'Generated by create-nx-workspace', +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + {children} + + ); +} diff --git a/apps/demo-nextjs-app/pages/index.module.css b/apps/demo-nextjs-app-router/app/page.module.css similarity index 100% rename from apps/demo-nextjs-app/pages/index.module.css rename to apps/demo-nextjs-app-router/app/page.module.css diff --git a/apps/demo-nextjs-app-router/app/page.tsx b/apps/demo-nextjs-app-router/app/page.tsx new file mode 100644 index 0000000..2313dd1 --- /dev/null +++ b/apps/demo-nextjs-app-router/app/page.tsx @@ -0,0 +1,170 @@ +'use client'; + +import * as fal from '@fal-ai/serverless-client'; +import { useMemo, useState } from 'react'; + +// @snippet:start(client.config) +fal.config({ + requestMiddleware: fal.withProxy({ + targetUrl: '/api/fal/proxy', // the built-int nextjs proxy + // targetUrl: 'http://localhost:3333/api/_fal/proxy', // or your own external proxy + }), +}); +// @snippet:end + +// @snippet:start(client.result.type) +type Image = { + url: string; + file_name: string; + file_size: number; +}; +type Result = { + images: Image[]; +}; +// @snippet:end + +type ErrorProps = { + error: any; +}; + +function Error(props: ErrorProps) { + if (!props.error) { + return null; + } + return ( +
+ Error {props.error.message} +
+ ); +} + +const DEFAULT_PROMPT = + 'a city landscape of a cyberpunk metropolis, raining, purple, pink and teal neon lights, highly detailed, uhd'; + +export default function Home() { + // @snippet:start("client.ui.state") + // Input state + const [prompt, setPrompt] = useState(DEFAULT_PROMPT); + // Result state + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + const [result, setResult] = useState(null); + const [logs, setLogs] = useState([]); + const [elapsedTime, setElapsedTime] = useState(0); + // @snippet:end + const image = useMemo(() => { + if (!result) { + return null; + } + return result.images[0]; + }, [result]); + + const reset = () => { + setLoading(false); + setError(null); + setResult(null); + setLogs([]); + setElapsedTime(0); + }; + + const generateImage = async () => { + reset(); + // @snippet:start("client.queue.subscribe") + setLoading(true); + const start = Date.now(); + try { + const result: Result = await fal.subscribe('110602490-lora', { + input: { + prompt, + model_name: 'stabilityai/stable-diffusion-xl-base-1.0', + image_size: 'square_hd', + }, + pollInterval: 5000, // Default is 1000 (every 1s) + logs: true, + onQueueUpdate(update) { + setElapsedTime(Date.now() - start); + if ( + update.status === 'IN_PROGRESS' || + update.status === 'COMPLETED' + ) { + setLogs((update.logs || []).map((log) => log.message)); + } + }, + }); + setResult(result); + } catch (error: any) { + setError(error); + } finally { + setLoading(false); + setElapsedTime(Date.now() - start); + } + // @snippet:end + }; + return ( +
+
+

+ Hello fal +

+
+ + setPrompt(e.target.value)} + onBlur={(e) => setPrompt(e.target.value.trim())} + /> +
+ + + + + +
+
+ {image && ( + // eslint-disable-next-line @next/next/no-img-element + + )} +
+
+

JSON Result

+

+ {`Elapsed Time (seconds): ${(elapsedTime / 1000).toFixed(2)}`} +

+
+              {result
+                ? JSON.stringify(result, null, 2)
+                : '// result pending...'}
+            
+
+ +
+

Logs

+
+              {logs.filter(Boolean).join('\n')}
+            
+
+
+
+
+ ); +} diff --git a/apps/demo-nextjs-app/index.d.ts b/apps/demo-nextjs-app-router/index.d.ts similarity index 100% rename from apps/demo-nextjs-app/index.d.ts rename to apps/demo-nextjs-app-router/index.d.ts diff --git a/apps/demo-nextjs-app/jest.config.ts b/apps/demo-nextjs-app-router/jest.config.ts similarity index 72% rename from apps/demo-nextjs-app/jest.config.ts rename to apps/demo-nextjs-app-router/jest.config.ts index f7a985d..6ff8152 100644 --- a/apps/demo-nextjs-app/jest.config.ts +++ b/apps/demo-nextjs-app-router/jest.config.ts @@ -1,11 +1,11 @@ /* eslint-disable */ export default { - displayName: 'demo-nextjs-app', + displayName: 'demo-nextjs-app-router', preset: '../../jest.preset.js', transform: { '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nx/react/plugins/jest', '^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nx/next/babel'] }], }, moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], - coverageDirectory: '../../coverage/apps/demo-nextjs-app', + coverageDirectory: '../../coverage/apps/demo-nextjs-app-router', }; diff --git a/apps/demo-nextjs-app/next-env.d.ts b/apps/demo-nextjs-app-router/next-env.d.ts similarity index 100% rename from apps/demo-nextjs-app/next-env.d.ts rename to apps/demo-nextjs-app-router/next-env.d.ts diff --git a/apps/demo-nextjs-app-router/next.config.js b/apps/demo-nextjs-app-router/next.config.js new file mode 100644 index 0000000..007b2aa --- /dev/null +++ b/apps/demo-nextjs-app-router/next.config.js @@ -0,0 +1,22 @@ +//@ts-check + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const { composePlugins, withNx } = require('@nx/next'); + +/** + * @type {import('@nx/next/plugins/with-nx').WithNxOptions} + **/ +const nextConfig = { + nx: { + // Set this to true if you would like to use SVGR + // See: https://github.com/gregberge/svgr + svgr: false, + }, +}; + +const plugins = [ + // Add more Next.js plugins to this list if needed. + withNx, +]; + +module.exports = composePlugins(...plugins)(nextConfig); diff --git a/apps/demo-nextjs-app/postcss.config.js b/apps/demo-nextjs-app-router/postcss.config.js similarity index 100% rename from apps/demo-nextjs-app/postcss.config.js rename to apps/demo-nextjs-app-router/postcss.config.js diff --git a/apps/demo-nextjs-app-router/project.json b/apps/demo-nextjs-app-router/project.json new file mode 100644 index 0000000..5b13833 --- /dev/null +++ b/apps/demo-nextjs-app-router/project.json @@ -0,0 +1,68 @@ +{ + "name": "demo-nextjs-app-router", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "apps/demo-nextjs-app-router", + "projectType": "application", + "targets": { + "build": { + "executor": "@nx/next:build", + "outputs": ["{options.outputPath}"], + "defaultConfiguration": "production", + "options": { + "outputPath": "dist/apps/demo-nextjs-app-router" + }, + "configurations": { + "development": { + "outputPath": "apps/demo-nextjs-app-router" + }, + "production": {} + } + }, + "serve": { + "executor": "@nx/next:server", + "defaultConfiguration": "development", + "options": { + "buildTarget": "demo-nextjs-app-router:build", + "dev": true + }, + "configurations": { + "development": { + "buildTarget": "demo-nextjs-app-router:build:development", + "dev": true + }, + "production": { + "buildTarget": "demo-nextjs-app-router:build:production", + "dev": false + } + } + }, + "export": { + "executor": "@nx/next:export", + "options": { + "buildTarget": "demo-nextjs-app-router:build:production" + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "apps/demo-nextjs-app-router/jest.config.ts", + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "codeCoverage": true + } + } + }, + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["apps/demo-nextjs-app-router/**/*.{ts,tsx,js,jsx}"] + } + } + }, + "tags": [] +} diff --git a/apps/demo-nextjs-app/public/.gitkeep b/apps/demo-nextjs-app-router/public/.gitkeep similarity index 100% rename from apps/demo-nextjs-app/public/.gitkeep rename to apps/demo-nextjs-app-router/public/.gitkeep diff --git a/apps/demo-nextjs-app-router/public/favicon.ico b/apps/demo-nextjs-app-router/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..317ebcb2336e0833a22dddf0ab287849f26fda57 GIT binary patch literal 15086 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 +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/apps/demo-nextjs-app/next.config.js b/apps/demo-nextjs-page-router/next.config.js similarity index 100% rename from apps/demo-nextjs-app/next.config.js rename to apps/demo-nextjs-page-router/next.config.js diff --git a/apps/demo-nextjs-app/pages/_app.tsx b/apps/demo-nextjs-page-router/pages/_app.tsx similarity index 100% rename from apps/demo-nextjs-app/pages/_app.tsx rename to apps/demo-nextjs-page-router/pages/_app.tsx diff --git a/apps/demo-nextjs-app/pages/api/_fal/proxy.ts b/apps/demo-nextjs-page-router/pages/api/_fal/proxy.ts similarity index 100% rename from apps/demo-nextjs-app/pages/api/_fal/proxy.ts rename to apps/demo-nextjs-page-router/pages/api/_fal/proxy.ts diff --git a/apps/demo-nextjs-page-router/pages/index.module.css b/apps/demo-nextjs-page-router/pages/index.module.css new file mode 100644 index 0000000..8a13e21 --- /dev/null +++ b/apps/demo-nextjs-page-router/pages/index.module.css @@ -0,0 +1,2 @@ +.page { +} diff --git a/apps/demo-nextjs-app/pages/index.tsx b/apps/demo-nextjs-page-router/pages/index.tsx similarity index 94% rename from apps/demo-nextjs-app/pages/index.tsx rename to apps/demo-nextjs-page-router/pages/index.tsx index 55a50f9..7fb7994 100644 --- a/apps/demo-nextjs-app/pages/index.tsx +++ b/apps/demo-nextjs-page-router/pages/index.tsx @@ -21,7 +21,11 @@ type Result = { }; // @snippet:end -function Error(props) { +type ErrorProps = { + error: any; +}; + +function Error(props: ErrorProps) { if (!props.error) { return null; } @@ -64,8 +68,7 @@ export function Index() { setElapsedTime(0); }; - const handleOnClick = async (e) => { - e.preventDefault(); + const generateImage = async () => { reset(); // @snippet:start("client.queue.subscribe") setLoading(true); @@ -85,12 +88,12 @@ export function Index() { update.status === 'IN_PROGRESS' || update.status === 'COMPLETED' ) { - setLogs(update.logs.map((log) => log.message)); + setLogs((update.logs || []).map((log) => log.message)); } }, }); setResult(result); - } catch (error) { + } catch (error: any) { setError(error); } finally { setLoading(false); @@ -121,7 +124,10 @@ export function Index() {