JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 10
  • Score
    100M100P100Q37312F
  • License MIT

Extended fal.ai client and server proxy with upload progress tracking

Package Exports

  • @rsemihkoca/fal-extended
  • @rsemihkoca/fal-extended/client
  • @rsemihkoca/fal-extended/proxy
  • @rsemihkoca/fal-extended/proxy/express

Readme

@rsemihkoca/fal-extended

All-in-one fal.ai package with client and server proxy including upload progress tracking.

πŸ“¦ One Package, Two Powers

npm install @rsemihkoca/fal-extended

This single package includes:

  • 🎯 Client - Browser/Node.js client with upload progress
  • πŸ”’ Proxy - Server proxy with storage handlers

πŸš€ Quick Start

Client-Side (Browser/React/Vue/etc)

import { fal } from '@rsemihkoca/fal-extended';

// Configure with your proxy
fal.config({
  proxyUrl: 'http://localhost:3000/api/fal/proxy'
});

// Upload with progress
const url = await fal.storage.upload(file, {
  onProgress: (e) => {
    console.log(`${e.progress}% - ${e.type}`);
    if (e.currentPart) {
      console.log(`Part ${e.currentPart}/${e.totalParts}`);
    }
  }
});

Server-Side (Express/Next.js/etc)

import express from 'express';
import * as fal from '@rsemihkoca/fal-extended/proxy/express';

const app = express();
app.use(express.json());

// Single line setup!
app.use(`${fal.route}/storage/upload`, fal.storageHandler);
app.use(fal.route, fal.handler);

app.listen(3000);

πŸ“š Import Paths

// Client
import { fal } from '@rsemihkoca/fal-extended';
// or
import { fal } from '@rsemihkoca/fal-extended/client';

// Proxy - Express
import * as fal from '@rsemihkoca/fal-extended/proxy/express';

// Proxy - Next.js
import * as fal from '@rsemihkoca/fal-extended/proxy/nextjs';

// Proxy - Hono
import * as fal from '@rsemihkoca/fal-extended/proxy/hono';

// Proxy - Core
import * as fal from '@rsemihkoca/fal-extended/proxy';

✨ Features

Client Features

  • βœ… All original fal.ai client APIs
  • πŸ†• Upload progress callbacks
  • πŸ†• Multipart upload progress (>90MB files)
  • πŸ†• Real-time upload tracking
  • πŸ†• Part-by-part progress for large files

Proxy Features

  • βœ… All original proxy features
  • πŸ†• Storage upload handlers
  • πŸ†• Single handler design
  • πŸ†• Automatic multipart detection
  • πŸ†• Secure credential handling
  • πŸ†• Framework support (Express, Next.js, Hono, Remix, SvelteKit)

πŸ“– Examples

React with Progress Bar

import { fal } from '@rsemihkoca/fal-extended';
import { useState } from 'react';

function FileUploader() {
  const [progress, setProgress] = useState(0);
  const [status, setStatus] = useState('');

  const handleUpload = async (file: File) => {
    const url = await fal.storage.upload(file, {
      onProgress: (e) => {
        setProgress(e.progress);
        setStatus(e.currentPart
          ? `Uploading part ${e.currentPart}/${e.totalParts}`
          : e.type
        );
      }
    });

    return url;
  };

  return (
    <div>
      <progress value={progress} max={100} />
      <p>{status}</p>
    </div>
  );
}

Complete Server Setup

import express from 'express';
import cors from 'cors';
import * as fal from '@rsemihkoca/fal-extended/proxy/express';

const app = express();

// Middleware
app.use(cors());
app.use(express.json());

// Logging (optional)
app.use((req, res, next) => {
  console.log(`${req.method} ${req.url}`);
  next();
});

// fal.ai routes
app.use(`${fal.route}/storage/upload`, fal.storageHandler);
app.use(fal.route, fal.handler);

// Start server
app.listen(3000, () => {
  console.log('πŸš€ Proxy server running on http://localhost:3000');
  console.log(`πŸ“‘ Storage endpoint: ${fal.route}/storage/upload`);
  console.log(`πŸ“‘ General proxy: ${fal.route}`);
});

Environment Variables

# .env
FAL_KEY=your-fal-key-here

# Or use separate key ID and secret
FAL_KEY_ID=your-key-id
FAL_KEY_SECRET=your-key-secret

πŸ” Security

NEVER expose FAL_KEY in the browser!

βœ… Correct:

// Client - uses proxy (credentials stay on server)
fal.config({ proxyUrl: 'https://your-server.com/api/fal/proxy' });

❌ Wrong:

// Client - exposes credentials!
fal.config({ credentials: 'fal-key-xxx' });

πŸ“Š Upload Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Client  │─────────────────▢│  Proxy  │────────────────▢│ fal.ai β”‚
β”‚ (Browser)β”‚  No credentials  β”‚ (Server)β”‚  With FAL_KEY  β”‚   API  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜
     β”‚                              β”‚
     β”‚  ◀───── signed URL ───────────
     β”‚
     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Storage β”‚  Direct upload (S3/CDN)
β”‚  (Fast!) β”‚  No proxy overhead!
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“„ Documentation

πŸ”— Framework Examples

Next.js App Router

// app/api/fal/[[...path]]/route.ts
export { GET, POST, PUT, DELETE } from '@rsemihkoca/fal-extended/proxy/nextjs';

Hono

import { Hono } from 'hono';
import * as fal from '@rsemihkoca/fal-extended/proxy/hono';

const app = new Hono();
app.use(`${fal.route}/storage/upload/*`, fal.storageHandler);
app.use(`${fal.route}/*`, fal.handler);

πŸ“¦ Package Size

This package includes both client and proxy code. If you only need one:

// Tree-shaking will remove unused code in production builds

// Only import what you need
import { fal } from '@rsemihkoca/fal-extended/client';  // Client only
import * as fal from '@rsemihkoca/fal-extended/proxy/express';  // Proxy only

πŸ†š Comparison

Feature Original fal.ai @rsemihkoca/fal-extended
Basic client βœ… βœ…
Server proxy βœ… βœ…
Upload progress ❌ βœ…
Multipart progress ❌ βœ…
Storage handlers ❌ βœ…
Single handler ❌ βœ…

πŸ“œ License

MIT

🀝 Contributing

Based on @fal-ai/client. Contributions welcome!

πŸ› Issues

Report issues at: https://github.com/rsemihkoca/fal-extended/issues