diff --git a/libs/nextjs/.babelrc b/libs/nextjs/.babelrc deleted file mode 100644 index fc2ad0f..0000000 --- a/libs/nextjs/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": [["@nx/js/babel", { "useBuiltIns": "usage" }]] -} diff --git a/libs/nextjs/.eslintrc.json b/libs/nextjs/.eslintrc.json deleted file mode 100644 index 9d9c0db..0000000 --- a/libs/nextjs/.eslintrc.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": {} - }, - { - "files": ["*.ts", "*.tsx"], - "rules": {} - }, - { - "files": ["*.js", "*.jsx"], - "rules": {} - } - ] -} diff --git a/libs/nextjs/README.md b/libs/nextjs/README.md deleted file mode 100644 index bf4ce8c..0000000 --- a/libs/nextjs/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# @fal-ai/serverless-nextjs - -This package is not longer maintained. Check out the [@fal-ai/serverless-proxy](../proxy/)package, which supports Next.js and other Express-based frameworks. diff --git a/libs/nextjs/jest.config.ts b/libs/nextjs/jest.config.ts deleted file mode 100644 index 4574120..0000000 --- a/libs/nextjs/jest.config.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'nextjs', - preset: '../../jest.preset.js', - globals: {}, - testEnvironment: 'node', - transform: { - '^.+\\.[tj]sx?$': [ - 'ts-jest', - { - tsconfig: '/tsconfig.spec.json', - }, - ], - }, - moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], - coverageDirectory: '../../coverage/libs/nextjs', -}; diff --git a/libs/nextjs/package.json b/libs/nextjs/package.json deleted file mode 100644 index b33a775..0000000 --- a/libs/nextjs/package.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "@fal-ai/serverless-nextjs", - "description": "The fal-serverless Next.js integration", - "version": "0.2.4", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/fal-ai/serverless-js.git", - "directory": "libs/nextjs" - }, - "keywords": [ - "fal", - "serverless", - "client", - "next", - "nextjs", - "proxy" - ], - "peerDependencies": { - "next": "^13.0.0", - "react": "^18.0.0", - "react-dom": "^18.0.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } -} diff --git a/libs/nextjs/project.json b/libs/nextjs/project.json deleted file mode 100644 index f4974ce..0000000 --- a/libs/nextjs/project.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "name": "nextjs", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "sourceRoot": "libs/nextjs/src", - "projectType": "library", - "targets": { - "build": { - "executor": "@nx/js:tsc", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/libs/nextjs", - "tsConfig": "libs/nextjs/tsconfig.lib.json", - "packageJson": "libs/nextjs/package.json", - "main": "libs/nextjs/src/index.ts", - "assets": ["LICENSE", "CODE_OF_CONDUCT.md", "libs/nextjs/README.md"] - } - }, - "lint": { - "executor": "@nx/linter:eslint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": ["libs/nextjs/**/*.ts"] - } - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "jestConfig": "libs/nextjs/jest.config.ts", - "passWithNoTests": true - }, - "configurations": { - "ci": { - "ci": true, - "codeCoverage": true - } - } - } - }, - "tags": [] -} diff --git a/libs/nextjs/src/config.ts b/libs/nextjs/src/config.ts deleted file mode 100644 index d440cbe..0000000 --- a/libs/nextjs/src/config.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { RequestMiddleware } from '@fal-ai/serverless-client'; - -export type NextProxyConfig = { - targetUrl: string; -}; - -const defaultConfig: NextProxyConfig = { - targetUrl: '/api/_fal/proxy', -}; - -export const TARGET_URL_HEADER = 'x-fal-target-url'; - -export function withNextProxy( - config: NextProxyConfig = defaultConfig -): RequestMiddleware { - // when running on the server, we don't need to proxy the request - if (typeof window === 'undefined') { - return (requestConfig) => Promise.resolve(requestConfig); - } - return (requestConfig) => - Promise.resolve({ - ...requestConfig, - url: config.targetUrl, - headers: { - [TARGET_URL_HEADER]: requestConfig.url, - ...(requestConfig.headers || {}), - }, - }); -} diff --git a/libs/nextjs/src/handler.ts b/libs/nextjs/src/handler.ts deleted file mode 100644 index 42983a3..0000000 --- a/libs/nextjs/src/handler.ts +++ /dev/null @@ -1,113 +0,0 @@ -import type { NextApiHandler, NextApiRequest, PageConfig } from 'next'; -import { TARGET_URL_HEADER } from './config'; - -const FAL_KEY = process.env.FAL_KEY || process.env.NEXT_PUBLIC_FAL_KEY; -const FAL_KEY_ID = process.env.FAL_KEY_ID || process.env.NEXT_PUBLIC_FAL_KEY_ID; -const FAL_KEY_SECRET = - process.env.FAL_KEY_SECRET || process.env.NEXT_PUBLIC_FAL_KEY_SECRET; - -/** - * Utility to get a header value as `string` from a Headers object. - * - * @private - * @param request the Next request object. - * @param key the header key. - * @returns the header value as `string` or `undefined` if the header is not set. - */ -function getHeader(request: NextApiRequest, key: string): string | undefined { - const headerValue = request.headers[key.toLowerCase()]; - if (Array.isArray(headerValue)) { - return headerValue[0]; - } - return headerValue; -} - -/** - * Clean up headers that should not be forwarded to the proxy. - * @param request the Next request object. - */ -function cleanUpHeaders(request: NextApiRequest) { - delete request.headers['origin']; - delete request.headers['referer']; - delete request.headers[TARGET_URL_HEADER]; -} - -function getFalKey(): string | undefined { - if (FAL_KEY) { - return FAL_KEY; - } - if (FAL_KEY_ID && FAL_KEY_SECRET) { - return `${FAL_KEY_ID}:${FAL_KEY_SECRET}`; - } - return undefined; -} - -/** - * A Next request handler that proxies the request to the fal-serverless - * endpoint. This is useful so client-side calls to the fal-serverless endpoint - * can be made without CORS issues and the correct credentials can be added - * effortlessly. - * - * @param request the Next request object. - * @param response the Next response object. - * @returns Promise the promise that will be resolved once the request is done. - */ -export const handler: NextApiHandler = async (request, response) => { - const targetUrl = getHeader(request, TARGET_URL_HEADER); - if (!targetUrl) { - response.status(400).send(`Missing the ${TARGET_URL_HEADER} header`); - return; - } - if (targetUrl.indexOf('fal.ai') === -1) { - response.status(412).send(`Invalid ${TARGET_URL_HEADER} header`); - return; - } - - cleanUpHeaders(request); - - const falKey = getFalKey(); - if (!falKey) { - response.status(401).send('Missing fal.ai credentials'); - return; - } - - // pass over headers prefixed with x-fal-* - const headers: Record = {}; - Object.keys(request.headers).forEach((key) => { - if (key.toLowerCase().startsWith('x-fal-')) { - headers[key.toLowerCase()] = request.headers[key]; - } - }); - - const res = await fetch(targetUrl, { - method: request.method, - headers: { - ...headers, - authorization: getHeader(request, 'authorization') ?? `Key ${falKey}`, - accept: 'application/json', - 'content-type': 'application/json', - 'x-fal-client-proxy': '@fal-ai/serverless-nextjs', - }, - body: - request.method?.toUpperCase() === 'GET' - ? undefined - : JSON.stringify(request.body), - }); - - // copy headers from res to response - res.headers.forEach((value, key) => { - response.setHeader(key, value); - }); - - if (res.headers.get('content-type') === 'application/json') { - const data = await res.json(); - response.status(res.status).json(data); - return; - } - const data = await res.text(); - response.status(res.status).send(data); -}; - -export const config: PageConfig = { - api: {}, -}; diff --git a/libs/nextjs/src/index.ts b/libs/nextjs/src/index.ts deleted file mode 100644 index 738ad61..0000000 --- a/libs/nextjs/src/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './config'; -export * from './handler'; diff --git a/libs/nextjs/tsconfig.json b/libs/nextjs/tsconfig.json deleted file mode 100644 index 62ebbd9..0000000 --- a/libs/nextjs/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ] -} diff --git a/libs/nextjs/tsconfig.lib.json b/libs/nextjs/tsconfig.lib.json deleted file mode 100644 index 3f06e80..0000000 --- a/libs/nextjs/tsconfig.lib.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "module": "commonjs", - "outDir": "../../dist/out-tsc", - "declaration": true, - "types": ["node"] - }, - "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"], - "include": ["src/**/*.ts"] -} diff --git a/libs/nextjs/tsconfig.spec.json b/libs/nextjs/tsconfig.spec.json deleted file mode 100644 index 26ef046..0000000 --- a/libs/nextjs/tsconfig.spec.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"] - }, - "include": [ - "jest.config.ts", - "src/**/*.test.ts", - "src/**/*.spec.ts", - "src/**/*.test.tsx", - "src/**/*.spec.tsx", - "src/**/*.test.js", - "src/**/*.spec.js", - "src/**/*.test.jsx", - "src/**/*.spec.jsx", - "src/**/*.d.ts" - ] -} diff --git a/libs/proxy/package.json b/libs/proxy/package.json index 121184e..656aad1 100644 --- a/libs/proxy/package.json +++ b/libs/proxy/package.json @@ -1,6 +1,6 @@ { "name": "@fal-ai/serverless-proxy", - "version": "0.3.3", + "version": "0.3.4", "license": "MIT", "repository": { "type": "git", diff --git a/libs/proxy/src/express.ts b/libs/proxy/src/express.ts index 939f107..7a2efd2 100644 --- a/libs/proxy/src/express.ts +++ b/libs/proxy/src/express.ts @@ -19,11 +19,10 @@ export const handler: RequestHandler = async (request, response, next) => { method: request.method, respondWith: (status, data) => typeof data === 'string' - ? response.status(status).send(data) + ? response.status(status).json({ details: data }) : response.status(status).json(data), getHeaders: () => request.headers, getHeader: (name) => request.headers[name], - removeHeader: (name) => response.removeHeader(name), sendHeader: (name, value) => response.setHeader(name, value), getBody: () => JSON.stringify(request.body), }); diff --git a/libs/proxy/src/index.ts b/libs/proxy/src/index.ts index 901f02c..1b78b24 100644 --- a/libs/proxy/src/index.ts +++ b/libs/proxy/src/index.ts @@ -18,7 +18,6 @@ export interface ProxyBehavior { respondWith(status: number, data: string | any): void; getHeaders(): Record; getHeader(name: string): string | string[] | undefined; - removeHeader(name: string): void; sendHeader(name: string, value: string): void; getBody(): string | undefined; } @@ -42,16 +41,6 @@ function singleHeaderValue( return value; } -/** - * Clean up headers that should not be forwarded to the proxy. - * @param behavior The proxy implementation. - */ -function cleanUpHeaders(behavior: ProxyBehavior) { - behavior.removeHeader('origin'); - behavior.removeHeader('referer'); - behavior.removeHeader(TARGET_URL_HEADER); -} - function getFalKey(): string | undefined { if (FAL_KEY) { return FAL_KEY; @@ -82,8 +71,6 @@ export const handleRequest = async (behavior: ProxyBehavior) => { return; } - cleanUpHeaders(behavior); - const falKey = getFalKey(); if (!falKey) { behavior.respondWith(401, 'Missing fal.ai credentials'); @@ -118,7 +105,7 @@ export const handleRequest = async (behavior: ProxyBehavior) => { behavior.sendHeader(key, value); }); - if (res.headers.get('content-type') === 'application/json') { + if (res.headers.get('content-type').includes('application/json')) { const data = await res.json(); behavior.respondWith(res.status, data); return; diff --git a/libs/proxy/src/nextjs.ts b/libs/proxy/src/nextjs.ts index 4492d4b..ea8b9f2 100644 --- a/libs/proxy/src/nextjs.ts +++ b/libs/proxy/src/nextjs.ts @@ -19,11 +19,10 @@ export const handler: NextApiHandler = async (request, response) => { method: request.method, respondWith: (status, data) => typeof data === 'string' - ? response.status(status).send(data) + ? response.status(status).json({ details: data }) : response.status(status).json(data), getHeaders: () => request.headers, getHeader: (name) => request.headers[name], - removeHeader: (name) => response.removeHeader(name), sendHeader: (name, value) => response.setHeader(name, value), getBody: () => JSON.stringify(request.body), }); diff --git a/tsconfig.base.json b/tsconfig.base.json index f845aa5..261ff37 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -16,7 +16,6 @@ "baseUrl": ".", "paths": { "@fal-ai/serverless-client": ["libs/client/src/index.ts"], - "@fal-ai/serverless-nextjs": ["libs/nextjs/src/index.ts"], "@fal-ai/serverless-proxy": ["libs/proxy/src/index.ts"], "@fal-ai/serverless-proxy/express": ["libs/proxy/src/express.ts"], "@fal-ai/serverless-proxy/nextjs": ["libs/proxy/src/nextjs.ts"]