diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1e20b85..3a0637f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,8 +16,8 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v3 with: - node-version: '18.x' - cache: 'npm' + node-version: "18.x" + cache: "npm" - name: Install dependencies run: npm ci - name: Format check diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e1094eb..2907c87 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,9 +17,9 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v3 with: - node-version: '16.x' - registry-url: 'https://registry.npmjs.org' - scope: '@fal' + node-version: "16.x" + registry-url: "https://registry.npmjs.org" + scope: "@fal" - name: Install dependencies run: npm ci - name: Publish to NPM diff --git a/README.md b/README.md index 3d87495..8b384ea 100644 --- a/README.md +++ b/README.md @@ -27,17 +27,17 @@ This client library is crafted as a lightweight layer atop platform standards li 2. Start by configuring your credentials: ```ts - import * as fal from '@fal-ai/serverless-client'; + import * as fal from "@fal-ai/serverless-client"; fal.config({ // Can also be auto-configured using environment variables: - credentials: 'FAL_KEY', + credentials: "FAL_KEY", }); ``` 3. Retrieve your function id and execute it: ```ts - const result = await fal.run('user/app-alias'); + const result = await fal.run("user/app-alias"); ``` The result's type is contingent upon your Python function's output. Types in Python are mapped to their corresponding types in JavaScript. @@ -56,13 +56,13 @@ For example, if you are using Next.js, you can: ``` 2. Add the proxy as an API endpoint of your app, see an example here in [pages/api/fal/proxy.ts](https://github.com/fal-ai/fal-js/blob/main/apps/demo-nextjs-page-router/pages/api/fal/proxy.ts) ```ts - export { handler as default } from '@fal-ai/serverless-proxy/nextjs'; + export { handler as default } from "@fal-ai/serverless-proxy/nextjs"; ``` 3. Configure the client to use the proxy: ```ts - import * as fal from '@fal-ai/serverless-client'; + import * as fal from "@fal-ai/serverless-client"; fal.config({ - proxyUrl: '/api/fal/proxy', + proxyUrl: "/api/fal/proxy", }); ``` 4. Make sure your server has `FAL_KEY` as environment variable with a valid API Key. That's it! Now your client calls will route through your server proxy, so your credentials are protected. diff --git a/apps/demo-express-app/jest.config.ts b/apps/demo-express-app/jest.config.ts index ca1fd62..acb63a0 100644 --- a/apps/demo-express-app/jest.config.ts +++ b/apps/demo-express-app/jest.config.ts @@ -1,11 +1,11 @@ /* eslint-disable */ export default { - displayName: 'demo-express-app', - preset: '../../jest.preset.js', - testEnvironment: 'node', + displayName: "demo-express-app", + preset: "../../jest.preset.js", + testEnvironment: "node", transform: { - '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], + "^.+\\.[tj]s$": ["ts-jest", { tsconfig: "/tsconfig.spec.json" }], }, - moduleFileExtensions: ['ts', 'js', 'html'], - coverageDirectory: '../../coverage/apps/demo-express-app', + moduleFileExtensions: ["ts", "js", "html"], + coverageDirectory: "../../coverage/apps/demo-express-app", }; diff --git a/apps/demo-express-app/src/main.ts b/apps/demo-express-app/src/main.ts index 7f11332..5b19b5f 100644 --- a/apps/demo-express-app/src/main.ts +++ b/apps/demo-express-app/src/main.ts @@ -3,34 +3,34 @@ * This is only a minimal backend to get started. */ -import * as fal from '@fal-ai/serverless-client'; -import * as falProxy from '@fal-ai/serverless-proxy/express'; -import cors from 'cors'; -import { configDotenv } from 'dotenv'; -import express from 'express'; -import * as path from 'path'; +import * as fal from "@fal-ai/serverless-client"; +import * as falProxy from "@fal-ai/serverless-proxy/express"; +import cors from "cors"; +import { configDotenv } from "dotenv"; +import express from "express"; +import * as path from "path"; -configDotenv({ path: './env.local' }); +configDotenv({ path: "./env.local" }); const app = express(); // Middlewares -app.use('/assets', express.static(path.join(__dirname, 'assets'))); +app.use("/assets", express.static(path.join(__dirname, "assets"))); app.use(express.json()); // fal.ai client proxy app.all(falProxy.route, cors(), falProxy.handler); // Your API endpoints -app.get('/api', (req, res) => { - res.send({ message: 'Welcome to demo-express-app!' }); +app.get("/api", (req, res) => { + res.send({ message: "Welcome to demo-express-app!" }); }); -app.get('/fal-on-server', async (req, res) => { - const result = await fal.run('110602490-lcm', { +app.get("/fal-on-server", async (req, res) => { + const result = await fal.run("110602490-lcm", { input: { prompt: - 'a black cat with glowing eyes, cute, adorable, disney, pixar, highly detailed, 8k', + "a black cat with glowing eyes, cute, adorable, disney, pixar, highly detailed, 8k", }, }); res.send(result); @@ -40,4 +40,4 @@ const port = process.env.PORT || 3333; const server = app.listen(port, () => { console.log(`Listening at http://localhost:${port}/api`); }); -server.on('error', console.error); +server.on("error", console.error); diff --git a/apps/demo-express-app/tsconfig.json b/apps/demo-express-app/tsconfig.json index 3c98d67..c1e2dd4 100644 --- a/apps/demo-express-app/tsconfig.json +++ b/apps/demo-express-app/tsconfig.json @@ -4,13 +4,13 @@ "include": [], "references": [ { - "path": "./tsconfig.app.json", + "path": "./tsconfig.app.json" }, { - "path": "./tsconfig.spec.json", - }, + "path": "./tsconfig.spec.json" + } ], "compilerOptions": { - "esModuleInterop": true, - }, + "esModuleInterop": true + } } diff --git a/apps/demo-express-app/webpack.config.js b/apps/demo-express-app/webpack.config.js index 81db92b..0ab513e 100644 --- a/apps/demo-express-app/webpack.config.js +++ b/apps/demo-express-app/webpack.config.js @@ -1,4 +1,4 @@ -const { composePlugins, withNx } = require('@nx/webpack'); +const { composePlugins, withNx } = require("@nx/webpack"); // Nx plugins for webpack. module.exports = composePlugins(withNx(), (config) => { 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 index 9a14c5c..db10d70 100644 --- a/apps/demo-nextjs-app-router/app/api/fal/proxy/route.ts +++ b/apps/demo-nextjs-app-router/app/api/fal/proxy/route.ts @@ -1,3 +1,3 @@ -import { route } from '@fal-ai/serverless-proxy/nextjs'; +import { route } from "@fal-ai/serverless-proxy/nextjs"; export const { GET, POST, PUT } = route; diff --git a/apps/demo-nextjs-app-router/app/camera-turbo/page.tsx b/apps/demo-nextjs-app-router/app/camera-turbo/page.tsx index 1c10e01..ce74a8d 100644 --- a/apps/demo-nextjs-app-router/app/camera-turbo/page.tsx +++ b/apps/demo-nextjs-app-router/app/camera-turbo/page.tsx @@ -1,15 +1,15 @@ /* eslint-disable @next/next/no-img-element */ -'use client'; +"use client"; -import * as fal from '@fal-ai/serverless-client'; -import { MutableRefObject, useEffect, useRef, useState } from 'react'; +import * as fal from "@fal-ai/serverless-client"; +import { MutableRefObject, useEffect, useRef, useState } from "react"; fal.config({ - proxyUrl: '/api/fal/proxy', + proxyUrl: "/api/fal/proxy", }); const EMPTY_IMG = - 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAA1JREFUGFdjOHPmzH8ACDADZKt3GNsAAAAASUVORK5CYII='; + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAA1JREFUGFdjOHPmzH8ACDADZKt3GNsAAAAASUVORK5CYII="; type WebcamOptions = { videoRef: MutableRefObject; @@ -65,7 +65,7 @@ const useWebcam = ({ canvas.width = width; canvas.height = height; - const context = canvas.getContext('2d'); + const context = canvas.getContext("2d"); if (context === null) { return; } @@ -80,7 +80,7 @@ const useWebcam = ({ 0, 0, width, - height + height, ); // Callback with frame data @@ -92,8 +92,8 @@ const useWebcam = ({ onFrameUpdate(frameData); }); }, - 'image/jpeg', - 0.7 + "image/jpeg", + 0.7, ); } }; @@ -143,22 +143,22 @@ export default function WebcamPage() { const previewRef = useRef(null); const { send } = fal.realtime.connect( - 'fal-ai/fast-turbo-diffusion/image-to-image', + "fal-ai/fast-turbo-diffusion/image-to-image", { - connectionKey: 'camera-turbo-demo', + connectionKey: "camera-turbo-demo", // not throttling the client, handling throttling of the camera itself // and letting all requests through in real-time throttleInterval: 0, onResult(result) { if (processedImageRef.current && result.images && result.images[0]) { const blob = new Blob([result.images[0].content], { - type: 'image/jpeg', + type: "image/jpeg", }); const url = URL.createObjectURL(blob); processedImageRef.current.src = url; } }, - } + }, ); const onFrameUpdate = (data: Uint8Array) => { @@ -166,7 +166,7 @@ export default function WebcamPage() { return; } send({ - prompt: 'a picture of george clooney, elegant, in a suit, 8k, uhd', + prompt: "a picture of george clooney, elegant, in a suit, 8k, uhd", image_bytes: data, num_inference_steps: 3, strength: 0.6, @@ -182,29 +182,29 @@ export default function WebcamPage() { }); return ( -
-

+
+

falcamera

- -
+ +
-
+
generated
diff --git a/apps/demo-nextjs-app-router/app/comfy/image-to-image/page.tsx b/apps/demo-nextjs-app-router/app/comfy/image-to-image/page.tsx index 6a4c4de..c8e9ab6 100644 --- a/apps/demo-nextjs-app-router/app/comfy/image-to-image/page.tsx +++ b/apps/demo-nextjs-app-router/app/comfy/image-to-image/page.tsx @@ -1,11 +1,11 @@ -'use client'; +"use client"; -import * as fal from '@fal-ai/serverless-client'; -import { useMemo, useState } from 'react'; +import * as fal from "@fal-ai/serverless-client"; +import { useMemo, useState } from "react"; // @snippet:start(client.config) fal.config({ - proxyUrl: '/api/fal/proxy', // the built-int nextjs proxy + proxyUrl: "/api/fal/proxy", // the built-int nextjs proxy // proxyUrl: 'http://localhost:3333/api/fal/proxy', // or your own external proxy }); // @snippet:end @@ -35,7 +35,7 @@ function Error(props: ErrorProps) { } return (
Error {props.error.message} @@ -44,7 +44,7 @@ function Error(props: ErrorProps) { } const DEFAULT_PROMPT = - 'photograph of victorian woman with wings, sky clouds, meadow grass'; + "photograph of victorian woman with wings, sky clouds, meadow grass"; export default function ComfyImageToImagePage() { // @snippet:start("client.ui.state") @@ -84,7 +84,7 @@ export default function ComfyImageToImagePage() { const start = Date.now(); try { const result: Result = await fal.subscribe( - 'comfy/fal-ai/image-to-image', + "comfy/fal-ai/image-to-image", { input: { prompt: prompt, @@ -94,13 +94,13 @@ export default function ComfyImageToImagePage() { onQueueUpdate(update) { setElapsedTime(Date.now() - start); if ( - update.status === 'IN_PROGRESS' || - update.status === 'COMPLETED' + update.status === "IN_PROGRESS" || + update.status === "COMPLETED" ) { setLogs((update.logs || []).map((log) => log.message)); } }, - } + }, ); setResult(getImageURL(result)); } catch (error: any) { @@ -112,16 +112,16 @@ export default function ComfyImageToImagePage() { // @snippet:end }; return ( -
-
-

+
+
+

Comfy SD1.5 - Image to Image

-
-